当前位置:网站首页>【六】redis缓存策略
【六】redis缓存策略
2022-07-28 05:21:00 【ymony】
核心内容概览:
收益:减少存储层IO,加速请求响应,减少后端访问量和计算,降低后端负载.
成本:存在数据一致性问题,增加了代码维护和运维成本
更新策略:
算法剔除:配置最大内存maxmemory 和过期策略 maxmemory-policy(LRU,LFU,FIFO)
- LRU:Least Recently Used,最近最少使用。
- LFU:Least Frequently Used,最不经常使用。
- FIFO:First In First Out,先进先出
超时剔除:expire 命令设置过期时间,到期删除
主动更新:真实数据更新后, 立即更新缓存数据

低一致性业务:建议配置最大内存和淘汰策略的方式使用。
高一致性业务:可以结合使用超时剔除和主动更新,这样即使主动更新出了问题,也能保证数据过期时间后删除脏数据。
可能存在的问题:
缓存穿透:大流量查询数据库不存在的数据可能致DB挂掉。解决方案:布隆过滤器,或者依然缓存空结果,但对key设置很短的过期时间(不超过5分钟)
缓存雪崩:大量缓存在某一时刻同时失效,DB 瞬时压力过重雪崩。解决方案:降低过期时间的重复率(比如在过期时间上增加1-5分钟的随机值)
缓存击穿:缓存在某个时间点过期的时候,恰好在这个时间点对这个 Key 有大量的并发请求过来,可能会瞬间压垮DB。(和缓存雪崩的区别在于这里针对某一 key )解决方法:互斥锁、永远不过期设置、资源保护等等
缓存无底洞问题:更多的机器(比如达到3000个节点)不代表更多的性能,解决方案有:串行 mget、串行 IO、并行 IO、Hash tag 实现。更多请看:缓存无底洞问题(http://ifeve.com/redis-multiget-hole/)
缓存的收益与成本
收益:
- 加速读写:CPU L1/L2/L3 Cache、浏览器缓存等。因为缓存通常都是全内存的(例如 Redis、Memcache),而 存储层通常读写性能不够强悍(例如 MySQL),通过缓存的使用可以有效 地加速读写,优化用户体验。
- 降低后端负载:帮助后端减少访问量和复杂计算,在很大程度降低了后端的负载。
成本:
- 数据不一致:缓存层和数据层有时间窗口不一致,和更新策略有关。
- 代码维护成本:加入缓存后,需要同时处理缓存层和存储层的逻辑, 增大了开发者维护代码的成本。
- 运维成本:以 Redis Cluster 为例,加入后无形中增加了运维成本。
使用场景:
- 降低后端负载:对高消耗的 SQL:join 结果集/分组统计结果缓存。
- 加速请求响应:利用 Redis/Memcache 优化 IO 响应时间。
- 大量写合并为批量写:比如计数器先 Redis 累加再批量写入 DB。
缓存更新策略—算法剔除
- LRU:Least Recently Used,最近最少使用。
- LFU:Least Frequently Used,最不经常使用。
- FIFO:First In First Out,先进先出。
使用场景:剔除算法通常用于缓存使用量超过了预设的最大值时候,如何对现有的数据进行剔除。例如 Redis 使用 maxmemory-policy 这个配置作为内存最大值后对于数据的剔除策略。
一致性:要清理哪些数据是由具体算法决定,开发人员只能决定使用哪种算法,所以数据的一致性是最差的。
维护成本:算法不需要开发人员自己来实现,通常只需要配置最大 maxmemory 和对应的策略即可。
缓存更新策略—超时剔除
使用场景:超时剔除通过给缓存数据设置过期时间,让其在过期时间后自动删除,例如 Redis 提供的 expire 命令。如果业务可以容忍一段时间内,缓存层数据和存储层数据不一致,那么可以为其设置过期时间。在数据过期后,再从真实数据源获取数据,重新放到缓存并设置过期时间。
一致性:一段时间窗口内(取决于过期时间长短)存在一致性问题,即缓存数据和真实数据源的数据不一致。
维护成本:维护成本不是很高,只需设置 expire 过期时间即可,当然前提是应用方允许这段时间可能发生的数据不一致。
缓存更新策略—主动更新
使用场景:应用方对于数据的一致性要求高,需要在真实数据更新后, 立即更新缓存数据。例如可以利用消息系统或者其他方式通知缓存更新。
一致性:一致性最高,但如果主动更新发生了问题,那么这条数据很可能很长时间不会更新,所以建议结合超时剔除一起使用效果会更好。
维护成本:维护成本会比较高,开发者需要自己来完成更新,并保证更新操作的正确性。
缓存更新策略—总结

低一致性业务:建议配置最大内存和淘汰策略的方式使用。
高一致性业务:可以结合使用超时剔除和主动更新,这样即使主动更新出了问题,也能保证数据过期时间后删除脏数据。
缓存可能会遇到的问题
缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能 DB 就挂掉了,要是有人利用不存在的 key 频繁攻击我们的应用,这就是漏洞。解决方法:
- 布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被 这个 bitmap 拦截掉,从而避免了对底层存储系统的查询压力。
- 另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
缓存雪崩:指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到 DB,DB 瞬时压力过重雪崩。解决方法:我们可以在原有的失效时间基础上增加一个随机值,比如 1-5 分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
缓存击穿:对于一些设置了过期时间的 key,如果这些 key 可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一 key 缓存,前者则是很多 key。缓存在某个时间点过期的时候,恰好在这个时间点对这个 Key 有大量的并发请求过来,这些请求发现缓存过期一般都会从后端 DB 加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端 DB 压垮。解决方法:互斥锁、永远不过期设置、资源保护等等。
缓存无底洞问题:Facebook 的工作人员反应 2010 年已达到 3000 个 memcached 节点,储存数千 G 的缓存。他们发现一个问题– memcached 的连接效率下降了,于是添加 memcached 节点,添加完之后,并没有好转。称为“无底洞”现象。原因:客户端一次批量操作会涉及多次网络操作,也就意味着批量操作会随着实例的增多,耗时会不断增大(eg:只有一个redis节点的服务器,一次mget命令只需一次网络和一个服务器io,但是如果是一个100个节点的redis集群,mget中多个key因为集群的hash函数映射可能分别分布在这100个节点上,那么就变为了100次分别到不同节点的网络和100次节点的get数据的io)。服务端网络连接次数变多,对实例的性能也有一定影响。即:更多的机器不代表更多的性能,所谓“无底洞”就是说投入越多不一定产出越多。
解决方案有:
- 串行 mget(即将mget拆为一个一个的单次get)
- 串行 IO(利用已知的hash函数算出各个key对应的节点,这样就可以得到一个这样的关系:Map<node, somekeys>,它的操作时间=node的个数次网络时间+key的个数次命令时间)、
- 并行 IO(将串行IO中的node节点次的网络进行多线程并发执行)
- Hash tag (即利用hash tag的{}属性,将所有的key都指定存到相同的节点上,下次便可只到一个节点获取)
实现等,更多请看:缓存无底洞问题(http://ifeve.com/redis-multiget-hole/)
四种批量操作解决方案对比:
文章参考:https://mp.weixin.qq.com/s/-3fcK4WspGk6SEsaVrdx8A
边栏推荐
猜你喜欢
随机推荐
ModuleNotFoundError: No module named ‘pip‘
js-promise实现逻辑
How digital library realizes Web3.0 social networking
渐进增强和优雅降级
数字藏品以虚强实,赋能实体经济发展
FlinkX安装及使用
区分实时数据、离线数据、流式数据以及批量数据的区别
简单理解一下MVC和三层架构
Progressive enhancement and graceful degradation
撞脸ins? Mars数字藏品平台探索数字藏品轻社交
MySQL view, stored procedure and stored function
(php毕业设计)基于php在线旅游网站管理系统获取
Continuous login problem
Books - the art of lucid thinking
话题功能实现
MarsNFT :个人如何发行数字藏品?
CMD and NPM basic commands
Acquisition of mental health service system based on PHP (PHP graduation design)
(php毕业设计)基于php校园网络报修管理系统获取
基于php小区疫情出入管理系统(php毕业设计)









