分布式缓存架构模式
数据缓存

设计核心:1、用什么缓存系统;2、如何应对数据一致性挑战
应用场景:实时性要求高的业务,读多写少的业务,例如:微博浏览
一致性设计
复杂度
读操作
- 读缓存系统
- 读不到再去读存储系统
写操作
先写缓存后写存储
写缓存成功写存储失败,单个数据在缓存有效期内读取没问题,但是关联业务会出异常,例如订单数据,用户自己能看到订单,但是系统统计不到这个订单
先写存储后写缓存
写存储成功写缓存失败,业务读到的是旧数据,缓存失效后才能更新为新数据
先删除缓存再写存储系统(适合用户相关数据)
正常情况下能保证数据一致性,但是缓存系统异常的时候,为了不影响写入存储系统,还是需要继续写入,同样会导致不一致
双删(适合全局数据)
先删除缓存,再写存储,再删除缓存
解决方案
容忍不一致性
方案
根据容忍度设定缓存的有效期,例如新闻资讯、微博、商品信息等
优缺点
- 简单
- 一定时期的数据不一致
关系数据库本地表事务
方案
- 正常的时候采用先删缓存后写入数据库的策略
- 缓存系统异常的时候,通过事务记录一条消息到本地消息表,然后后台定时读取消息表记录,重试删除操作
优缺点
- 复杂
- 数据不一致时间短,等于重试间隔
消息队列异步删除
方案
- 正常的时候采用先删除缓存后写入数据库的策略
- 缓存系统异常的时候,发送一条删除操作给消息队列,然后后台读取消息队列记录,重试删除操作
优缺点
- 复杂
- 数据不一致时间短,等于重试间隔
- 消息队列可能挂掉
结果缓存

设计核心:1、用什么缓存系统;2、缓存有效期与结果新鲜度的平衡
应用场景:计算量大但实时性要求不高的业务场景,例如推荐、热榜、排行榜、分页
分布式缓存架构设计思路

三类问题
缓存穿透
缓存里面没有数据
定义
缓存没有发挥作用,业务系统虽然去缓存查询数据,但缓存中没有数据,业务系统需要再次去存储系统中查询数据
场景
- 存储系统中确实不存在被访问的数据
- 存储中存在,但缓存中不存在的数据
- 系统刚启动的时候,大量缓存还没有生成
- 缓存集中失效
应对方法
方法1:空值缓存

应对被攻击或被爬虫试探
方法2:缓存当前数据

应对爬虫爬取或用户翻页到中部或尾部
方法3:缓存预热
应对运营活动、秒杀、大促等场景
- 模拟请求触发系统生成缓存,实现比较复杂
- 后台按照规则批量生成缓存,实现工作量较大
- 灰度发布/预发布触发系统生成缓存(推荐)
方法4:随机失效
缓存有效期设定为一个时间范围内的随机值。应对后台批量生成的缓存
缓存雪崩
缓存失效引起雪崩效应

根因:存储读取数据太耗费时间

根因:生成缓存的计算任务太耗时间
技术本质

根因:1、生成缓存较慢(复杂的数据查询、大量的计算等);2、缓存失效后并发请求量较大
应对方法
方法1:更新锁
方案
- 对缓存更新操作进行加锁保护,保证只有一个线程能够进行缓存更新
- 未能获取更新锁的线程要么等待锁释放后重新读取缓存,要么就返回空值或者默认值
优缺点
- 需要引入分布式锁
- 能够保证只有一个线程能更新
方法2:后台更新
方案
- 由后台线程来更新缓存,而不是由业务线程来更新缓存
- 缓存有效期设置为永久,后台线程更新缓存,更新策略分为“定时更新”、“事件触发更新”
- 业务线程只读取缓存,缓存不存在就返回空值
优缺点
- 实现简单
- 需要保证后台线程高可用
缓存热点
部分缓存访问量超高。例如:热点事件、突发事件
应对方法

方案细节
- 写入的时候,缓存的key加上编号,写入到多个缓存服务器
- 读取的时候随机生成编号组装key,然后读取
挑战
不太好预料哪些key是热点(微博的热点事件),需要动态决策或者人工干预