前述
本篇内容为草稿。记录Redis在项目中的一些实际应用,不会具体写,只写写简单的思路。
医院距离排序
需求描述
根据用户的定位信息(经纬度)获取周围的医院,然后再通过医院获取医生。
解决思路
方案-: MySQL数据库直接存储经纬度,然后每次查询都计算距离并排序。缺点是每次计算会比较慢,而且不能缓存。
方案二: MySQL官方支持的GEO方案,但是目前不太完善,使用不是很方便。
方案三:基于MongoDB的GEO方案,MongoDB对GEO支持还是很好的,但是为了方便聚合其他信息和利用缓存,我们这里不使用。
方案四:基于Redis的GEO方案。
具体实现
医院数量有限,因此可以将所有医院的位置信息用Redis的GEO数据结构存储,借助Redis快速实现距离筛选。
为了能存储更多信息且只管一点,采用id:name
作为key。
GEOADD hospitalGeo 123 89 美肤医院:1
Redis GEO参考 Redis Geo实战
利用georadius
和georadiusbymember
按距离返回key,可以排序。
拿到id后再去医院数据库过滤医生。
问题思考
Q:医院位置更新了怎么办?
A:采用同时更新Redis和数据库的办法同步。
Q: Redis重启了怎么办?
A:写一个脚本,数据预热。
Q:怎样集合搜索和医院位置排序
A:现在的做法是先查询出5km范围的医院,然后再带着这些id去数据库搜索(后面想通过redis集合)
和推荐排序搭配
见多种排序组合小节
缓存管理后台用户权限
需求场景描述
一家美容医院有多个门店,要求总部管理员可以看到门店的订单等信息,门店的医生只能看到自己信息。
解决方案
利用set存储每个用户对应可以访问医院门店(只存储医院管理员,可以访问所有门店数据)。基于一个医院管理员很多,但是实际经常登录查看数据的账号估计就几个,设置key过期时间。
更好方案:将每个用户的基本信息json_dump后存入对应key,如mb:user:1。使用的时候解锁对应数据。
实现医生和医院列表
基于zset,key为docter:following:userid。成员为关住医院或医生id,score为关注时间,方便利用关注时间排序。设置过期时间,如果过期从数据库取。为了节省内存空间,关注列表最多保留100条。如果用户特殊情况需要访问操过100条,从数据库读取。
医院医生列表排序
需求场景
根据search(项目名)搜索框,搜索医院信息,然后根据平均评分,好评率,位置信息排序。
医生也有类似的需求。
解决方案
方案以医院为例,医生也类似的解决方案。
1, 每家医院用一个hash结构存储医院基本信息,其中信息包括:医院名,平均评分,好评率,预约数,城市代码等。可以保存到硬盘,下次启动方便加载进来,不然预热太慢。
2,用三个sorted set(有序集合,后面写为zset)存储分别按平均评分,好评率,预约数为维度的医院排序信息,其中医院id为项,各维度为score。zset score自动从小到大排序。为了节约空间,只保留最多200条排序,通过定时任务清楚多余的排序。
3,用一个GEO存储所有医院的经纬度(因为列表和详情都需要展示距离,所以这个不打算设置过期时间,如果Redis重启,会执行数据预热脚本填充对应数据)。
4,每个医美项目用一个set(普通集合)存储包含的医院。大约有200多个项目。
5,利用对应的项目set和排序zset执行ZINTERSTORE
命令(交集并存储),聚合方式为MAX
。结果存储key为sort:hospital:userid。为了节约内存,这个结果不能存储太长时间,默认5分钟。
6,基于异步定时任务更新医生平均评分,好评率,预约数。每次更新,没必要所有医院(医生)的评论信息都更新,只有在预约数,或者评论更新时才需要更新。可以基于celery异步任务更新。
7,删除医院和医生时,同步删除缓存里医院和医生对应key,并且从排名有序集合中删除。再从项目对应关系中删除(难点,不知道那些项目包含医院或医生)。
下面是一些更新命令:
zadd key score member 在key存在的情况下更新有序集合成员
zrem key member member 删除一个或多个有序集合成员
sadd, srem对应集合的添加删除
HDEL key field [field ...]
HSET key field value
问题
Q: 有序集合多个member score相同,这时候根据字典排序,就会导致11的id排到1前面,这种情况如何解决?
可以将现在时间-创建时间的差值加上score,这样相同的score,后面创建的数值比较小。
Q: 如何设置医院和医生的过期时间?需要避免频繁访问的过期时间短,同时避免同时失效。
A: 默认过期时间基数10天,然后获取最近访问时间,10天以内的,随机加上6-10的数字,10-20天以内的,随机加上1-5的天数,20-30不加。30-60随机见1-5天,60天以上随机减6-10天。
初始值8-15天随机。
然后访问的时候,列表自动更新3-5天,详情自动6-8天。但是不大于30天。
Q: 项目对应的医院和医生是否设置过期时间,如何更新它的值?如何根据访问频繁度来缓存。
A: 设置,如果访问了,就更新过期时间,随机延长一个范围值。
Q: 医院或医生删除,如何快速找到关联了哪些项目,并删除里面的对应关系。
暂未解决,只能暴力查找。