前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >分布式系统的缓存设计你真的会了吗?

分布式系统的缓存设计你真的会了吗?

作者头像
JavaEdge
发布2021-03-29 16:34:22
发布2021-03-29 16:34:22
7900
举报
文章被收录于专栏:JavaEdgeJavaEdge

缓存不仅加快了IO,还可减少原始数据的计算工作。

缓存系统一般设计简单,功能单一,所以Redis吞吐量能是MySQL几倍~几十倍,对于互联网读多写少的高并发场景已不可或缺。

虽然简单好用,但是如果姿势不对,就会造成不必要的损失。

不要把Redis当数据库

很多人不仅把 redis 当缓存,更是把Redis当做数据库使用。很多因为Redis中数据消失导致业务逻辑错误,并且因为没有保留原始数据,业务都无法恢复。

虽然Redis有持久化功能,但这并不能以为它可作为高性能的KV数据库。 Redis处理请求很快,但那是因为在内存中,无法保存超过内存大小的数据。

因此,再将Redis用作缓存时,需要注意:

  • 客户端角度看,缓存数据的特点一定是有原始数据来源,且允许丢失,即使设置的缓存时间是1min,在30s时缓存数据因为某种原因消失了,也要能接受。当数据丢失后,需要从原始数据重新加载数据,永远不要认为缓存是绝对可靠的,也不要认为缓存不会删除没有过期的数据。
  • Redis服务端来看,缓存可以保存的数据量一定小于原始数据 应该限制Redis内存使用量,即maxmemory参数 根据数据特点,明确Redis数据淘汰策略

这些策略是Key范围+Key选择算法的搭配组合,范围有allkeys和volatile两种,算法有LRU、TTL和LFU三种。

如何选择合适的驱逐算法

算法角度

Redis 4.0以后推出的LFU比LRU更“实用”。试想一下,如果一个Key访问频率是1天一次,但正好在1秒前刚访问过,那么LRU可能不会选择优先淘汰这个Key,反而可能会淘汰一个5秒访问一次但最近2秒没有访问过的Key,而LFU算法不会有这个问题。而TTL会比较“头脑简单”一点,优先删除即将过期的Key,但有可能这个Key正在被大量访问。

Key范围角度

allkeys可确保即使Key没有TTL也能回收,如果使用的时候客户端总是“忘记”设置缓存的过期时间,那么可以考虑使用这系列算法。 而volatile会更稳妥,万一客户端把Redis当做了长效缓存,只是启动时候初始化一次缓存,那么一旦删除了此类没有TTL的数据,可能就会导致客户端出错。

缓存数据同步策略

实际开发中,如果修改了原始数据,考虑到缓存数据更新的及时性,我们可能会采用主动更新缓存的策略:

先更新缓存,再更新数据库

不可行。数据库设计复杂,压力集中,数据库因为超时等原因更新操作失败的可能性较大,此外还会涉及事务,很可能因为数据库更新失败,导致缓存和数据库的数据不一致。

先更新数据库,再更新缓存

不可行:

  • 如果线程A、B先后完成数据库更新,但更新缓存时却是B和A的顺序,那很可能会把旧数据更新到缓存中引起数据不一致
  • 我们不确定缓存中的数据是否会被访问,不一定要把所有数据都更新到缓存

先删除缓存,再更新数据库,访问时候按需加载数据到缓存

不可行。并发情况下,很可能删除缓存后还没来得及更新DB,就有另一个线程先读取旧值到缓存中去。并发量高时,概率还很大。

先更新DB,再删缓存,访问时按需加载数据至缓存

最好。虽然在极端情况下,这种策略也可能出现数据不一致,但概率很低,基本可以忽略。 一个极端的例子,更新数据的时间节点恰好是缓存失效了:

  • 【查询线程A】,先读取到了DB的旧值
  • 随后【更新线程B】操作DB完成更新,并删除缓存后
  • 【查询线程A】再把旧值加入缓存

更新DB后,删除缓存的操作可能失败,若失败则考虑把任务加入延迟队列进行延迟重试,确保数据可以删除,缓存可以及时更新。因为删除操作是幂等的,所以即使重复删,问题也不大,这也是删除比更新缓存好的一个原因。

所以对于缓存更新,推荐缓存中的数据不由数据更新操作主动触发,统一在需要使用的时候按需加载,数据更新后及时删除缓存中的数据即可。 并且要尽量设置合适的缓存过期时间,这样即便真的发生不一致,也可以在缓存过期后数据得到及时同步。

使用缓存系统的时候,要监控缓存系统的内存使用量、命中率、对象平均过期时间等重要指标,以便评估系统的有效性,并及时发现问题。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/03/23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 不要把Redis当数据库
  • 如何选择合适的驱逐算法
    • 算法角度
    • Key范围角度
  • 缓存数据同步策略
    • 先更新缓存,再更新数据库
    • 先更新数据库,再更新缓存
    • 先删除缓存,再更新数据库,访问时候按需加载数据到缓存
    • 先更新DB,再删缓存,访问时按需加载数据至缓存
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档