主题切换
缓存击穿
一、定义
单个热点Key到期瞬间,海量并发请求绕过Redis,直接访问MySQL。高频访问的热点数据缓存失效时,大量请求同时查询数据库,容易压垮DB。
二、场景举例
爆款文章对应的缓存Key过期,同一时刻大量请求到达。Redis查询不到数据,所有请求直接穿透至数据库查询。
三、四种主流解决方案
1. 分布式互斥锁(Redisson实现)
缓存失效时,仅允许抢到分布式锁的一个请求查询数据库并回写缓存;其余请求阻塞等待,待缓存刷新完成后再读取Redis。 优点:数据一致性强; 缺点:部分请求会被阻塞,降低接口吞吐量。
2. 逻辑过期(异步更新缓存)
不给Key设置物理过期时间,在Value内部嵌入逻辑过期时间戳。
- 检测到缓存逻辑过期,抢到锁的线程开启异步子线程,查询数据库并刷新缓存、更新时间戳;
- 主线程以及其他未抢到锁的请求,直接返回旧缓存数据,全程不阻塞、不访问数据库。 优点:请求无阻塞,并发性能高; 缺点:会短暂返回过期数据,无法做到强一致性,适用于商品、资讯等可容忍短暂脏读的业务。
3. 热点Key永不过期
热点数据不设置Redis物理过期时间,通过后台定时任务主动刷新缓存,从根源避免因Key过期引发击穿。 优点:彻底杜绝缓存击穿风险; 缺点:需要额外开发定时刷新任务。
4. 过期时间增加随机偏移量
在原有过期时间基础上增减随机毫秒数,打散过期时间,避免大量热点Key同时失效,同时可顺带缓解缓存雪崩。
四、缓存击穿与缓存穿透区分
- 缓存击穿:热点Key过期,数据在数据库中真实存在,大量并发请求查询同一条有效数据。
- 缓存穿透:查询数据库中不存在的数据,缓存始终无数据,请求每次都会直达数据库。
五、面试高频问题解析
问:什么是缓存击穿,会造成什么影响?
答: 热点缓存Key过期后,海量并发请求绕过Redis直接访问MySQL。高并发场景下会瞬间增大数据库压力,严重时压垮数据库。
问:介绍几种解决缓存击穿的方案及优缺点?
答: 一是分布式锁,控制单线程查库更新缓存,一致性好但会阻塞请求;二是逻辑过期,异步刷新缓存,并发性能高但会短暂返回旧数据;三是热点Key永不过期,配合定时任务刷新,实现简单无击穿风险;四是过期时间加随机偏移,打散过期节点,成本最低。
问:逻辑过期方案适用什么业务场景?
答: 适合可以短暂容忍数据不一致、追求高并发吞吐的业务,例如商品展示、资讯文章等,不适合订单、支付等对数据实时性要求极高的场景。
问:如何快速区分缓存击穿和缓存穿透?
答: 击穿针对数据库存在的热点数据,由Key过期引发;穿透针对数据库不存在的数据,缓存一直无法命中,两类问题成因与应对方案均不相同。