前述

本篇内容为草稿。记录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实战

利用georadiusgeoradiusbymember按距离返回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: 医院或医生删除,如何快速找到关联了哪些项目,并删除里面的对应关系。

暂未解决,只能暴力查找。

后述

敖丙面试宝典


Published

Category

Redis

Tags

Stay in Touch

Friendship Links