企业级解决方案之缓存预热,缓存雪崩,缓存穿透,缓存击穿
缓存预热
问题排查
- 请求数量较高
- 主从之间数据吞吐量较大,数据同步操作频度较高
解决方案
-
前置准备工作
- 日常例行统计数据访问记录,统计访问频度较高的热点数据
- 利用LRU数据删除策略,构建数据留存队列
- 例如 storm与kafka配合
-
准备工作
- 将统计结果中的数据分类,根据级别,redis优先嘉爱级别较高的热点数据
- 利用分布式多服务器同时进行数据读取,快速数据加载过程
-
实施
- 使用脚本程序固定触发数据预热过程
- 如果条件允许,使用CDN,
总结
缓存预热急事系统启动前,提前将想换的缓存数据直接记载到缓存系统,避免用户请求的时候,先查询数据库,然后再将数据缓存的问题!! 用户直接查询数据库事先被预热的缓存数据!!
缓存雪崩
大量的key失效或者缓存发成了宕机,导致原本被缓存抵挡的海量查询请求就会涌向数据库,此时的数据库如果抵挡不住这巨大的压力,它就会崩溃
对比
- 缓存雪崩针对很多 key 失效导致redis无法命中,数据库压力激增;
- 缓存击穿则是某一个热门 key 失效导致redis无法命中,数据库压力激增
缓存雪崩现象: 数据库压力变大,服务器崩溃
雪崩出现原因: 极小时间段内,redis中大量的key过期,导致命中率极低,数据库压力激增
解决方案(熔断器)
- 构建多级缓存架构: nginx 缓存 + redis 缓存 +其他缓存(ehcache 等),程序设计较为复杂
- 使用锁或队列:
用加锁或者队列的方式来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。效率低,不适用高并发情况 - 设置过期标志更新缓存: 记录缓存数据是否过期(设置提前量),如果过期会触发通知另外的线程在后台去更新实际 key 的缓存
- 将缓存失效时间分散开: 比如我们可以在原有的失效时间基础上增加一个随机值,比如 1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件
缓存击穿
- 单个/多个热点数据失效,导致大量的请求直接进入到数据库
解决方案
- 热点数据不设置过期时间
- 设置过期时间的时候,添加随机数。避免大量热点数据同时失效
- 设置多级缓存
缓存穿透
数据库中不存在的key被频繁的访问,导致请求直接穿过redis访问数据库,一般是恶意攻击
解决方案
- 布隆过滤器