-
缓存击穿是指:某一热点 key 在缓存和数据库中都存在,它过期时,这时由于并发用户特别多,同时读缓存没读到,又同时去数据库去读,压垮数据库
-
解决方法
-
热点数据不过期
-
对【查询缓存没有,查询数据库,结果放入缓存】这三步进行加锁,这时只有一个客户端能获得锁,其它客户端会被阻塞,等锁释放开,缓存已有了数据,其它客户端就不必访问数据库了。但会影响吞吐量(有损方案)
-
-
情况1:由于大量 key 设置了相同的过期时间(数据在缓存和数据库都存在),一旦到达过期时间点,这些 key 集体失效,造成访问这些 key 的请求全部进入数据库。
-
解决方法:
-
错开过期时间:在过期时间上加上随机值(比如 1~5 分钟)
-
服务降级:暂停非核心数据查询缓存,返回预定义信息(错误页面,空值等)
-
-
情况2:Redis 实例宕机,大量请求进入数据库
-
解决方法:
-
事前预防:搭建高可用集群
-
多级缓存:缺点是实现复杂度高
-
熔断:通过监控一旦雪崩出现,暂停缓存访问待实例恢复,返回预定义信息(有损方案)
-
限流:通过监控一旦发现数据库访问量超过阈值,限制访问数据库的请求数(有损方案)
-
-
缓存穿透是指:如果一个 key 在缓存和数据库都不存在,那么访问这个 key 每次都会进入数据库
-
很可能被恶意请求利用
-
缓存雪崩与缓存击穿都是数据库中有,但缓存暂时缺失
-
缓存雪崩与缓存击穿都能自然恢复,但缓存穿透则不能
-
-
解决方法
-
如果数据库没有,也将此不存在的 key 关联 null 值放入缓存,缺点是这样的 key 没有任何业务作用,白占空间
-
布隆过滤器
① 过滤器可以用来判定 key 不存在,发现这些不存在的 key,把它们过滤掉就好
② 需要将所有的 key 都预先加载至布隆过滤器
③ 布隆过滤器不能删除,因此查询删除的数据一定会发生穿透
-
-
旁路缓存(Cache Aside),是一种常见的使用缓存的策略
-
查询规则
-
先读缓存
-
如果命中,直接返回
-
如果缺失,查 DB 并将结果放入缓存,再返回
-
-
增、删、改规则
-
新增数据,直接存 DB
-
修改、删除数据,先更新DB,再删缓存
-
为什么要先操作库,再操作缓存?
假设操作库和缓存均能成功,如果先操作缓存,会大几率出现数据库与缓存不一致的情况
一致性分析 - 先清缓存,再更新库
一致性分析 - 先更新库,再清缓存
-
会有短暂不一致,但最终会一致
-
假设查询线程 A 查询数据时恰好缓存数据由于时间到期失效,或是第一次查询,会如上图所示出现不一致
-
但这种几率出现机会很小
用锁解决一致性
-
缺点:影响吞吐量、分布式锁设计较为复杂



