前言
好久不更新博客了,我又来更新了。这次遇到的问题是 redis 里面删除 key 和 查询 key。
项目背景
老规矩,开头说一下项目背景。原商城项目二开,客户要求增加一个附近功能,而附近商家功能,我们以前已经有了,所以只需要打开上上去就行了。
问题
如果真是这么简单,那我岂不是没有文章可以写了?当然不是。把项目上到测试环境后,产品测试了一下,反馈说不能管理首页的 banner 和商品列表。我的第一反应就是:这个功能是好的,肯定是新来的产品啥都不懂。但为了防止被打脸,我特地试了一下,结果真的有问题。查看代码,发现是后台删除了 redis,但是没有删除完。因为有N个程序员开发过这一块,所以导致了这一块的功能特别拥挤,像屎一样,各种骚操作。现在需求是:每个城市每个地区都有对应的商家供其选择,如果没有商家,默认就取一个指定的城市。某一任程序员就写了一个神奇的操作:如果后台没有某个城市的数据,就取默认城市的数据放到该城市里面去,那么这里就有一个神奇的事情发生了:后台管理城市数据的时候,比如更新或者删除城市数据,但是前端并没有该城市数据,导致了后台删除了相关的redis,并没有删除那些已经存在的 redis 。例如:用户在前端请求北京市的数据,但是后台并没有北京市,所以默认把深圳市的数据给了北京,并且缓存到 redis 的 key 为北京的数据里面了,此时,在后台更新深圳市或者新增北京的时候,redis 并没有做相应的更新操作。
解决方案
那么如何解决这个问题呢?
我为了图快,我是直接增加了一个集合。设置一个集合,不存在的 key 都放在集合里面,这样每次可以判断在不在集合里面了,而后台删除的时候,判断对应的城市key是否存在集合里面,存在就删除集合里面的对应的值。其它逻辑照常执行。比如已经存在的城市缓存就直接删除(unlink)
后台为什么不做写操作?
因为这个key可能很久都没有访问
后记
效率及功能分析
当时改这段逻辑的时候,各种考虑,最后还是用了这种方式,原因为:set比list少一点重复,也就是说不用管数据重复问题。为什么不使用有序集合,因为不需要排序,只需要知道是否存在就行了。
业务方面分析:
原始版本:无法删除对应城市 redis 缓存
修改了第一版本:增加了集合,后台删除的时候,使用 hscan + unlink 删除集合和已经缓存的城市 key,然后原始逻辑不变。最快实现。此时问题:前端请求后台不存在的城市数据会缓存到内存中,造成内存的浪费。
修改了第二版本:前端先判断这个城市数据是否存在,如果不存在,判断集合中是否存在这个城市值,如果存在,返回默认的城市的缓存。而后台只需要删除集合里面需要新增的值就行了。
鸣谢
感谢大佬们的文章参考
参考
https://blog.csdn.net/u012998306/article/details/105417611 redis sadd 命令 以及 删除set集合或者单独删除set中的一/多条记录
https://bbs.huaweicloud.com/blogs/317523 为了拿捏 Redis 数据结构,我画了 40 张图(完整版)
https://blog.csdn.net/fuzhongmin05/article/details/119531696 数据结构如何造就Redis的快
http://jinguoxing.github.io/redis/2018/09/04/redis-scan/ scan的使用
https://www.lixueduan.com/post/redis/redis-scan/ Redis Scan 原理解析与踩坑
https://nyogjtrc.github.io/posts/2019/12/delete-keys-matching-a-pattern-in-redis/ 刪除 Redis 中符合 Pattern 的 Key
https://redis.io/commands/unlink/ unlink
http://mysql.taobao.org/monthly/2018/10/05/ redis lazyfree · 大key删除的福音
https://blog.csdn.net/loophome/article/details/105204427 Redis删除大集合操作(Lists,Sets)
评论 (0)