缓存穿透、缓存雪崩、缓存击穿问题与优化方案
在使用缓存(如 redis)的应用中,我们需要对常见的问题做好相关技术方案的设计和应对,以充分应对或减少可能出现的线上故障
1、缓存穿透
缓存穿透在于缓存中不存在数据,数据库中也查询不到数据。这种情况更多的可能是恶意攻击,通过提供数据库中不存在的值,来暴力压垮数据库,类似针对数据库的 DDos 攻击。
优化方案(参考关键字段id
):
方案 1 针对数据库中不存在的值,返回时,也创建相应 id 缓存 key,value 可以是默认的空值或其他。
优势:
a、该方案可以保证对于数据库的请求时一次性的,可以拦截后续重复的请求
b、实现简单、直接
不足:
a、如果攻击提供的查询值不重复,则无法有效缓存
b、不断累加的缓存 key 浪费缓存空间
方案 2 维护最大 id 缓存信息,超出的数据直接拒绝
优势:
a、在发布内容后需要维护最大 id 信息
b、实现也相对比较简单
不足:
1、仅满足关键值如 id 信息连续或数据不稀疏的场景
2、维护最大 id 等需要原子性以保持并发和递增等一致性
3、最大 id 缓存存在一定的初次写入成本
4、数据查询数据库时,多一次缓存 id 判定操作
方案 3 使用布隆过滤器
优势:
1、有开源的工具类可以使用且可实现 redis 分布式版本
2、空间占用少
不足:
1、多次哈希性能开销
2、对于存在的数据有一定误判率,且随着数据增加,误判率会增大
3、对于存在数据需要启动并热数据
4、无法删除数据,不适合数据删除场景较多的情况
2、缓存雪崩
缓存雪崩主要针对大量的缓存在同一时间集体失效,导致大量的查询直接透传到数据库层面,从而压垮数据库。
优化方案:
调整缓存 key 过期时间策略为:基本过期时间+随机时间
优势:
简单直接
不足:无
3、缓存击穿
主要是由于数据访问用户并发高,由于缓存失效等原因,并发请求同时发起数据库读取操作,引起数据库压力瞬间增大的情况。
优化方案:
方案一 设置热点数据永不过期
优势:
1、实现最简单
不足:
1、需要 task 等其他方式维护数据更新
方案二 单机并发时,应用级别锁控制并发,仅保留 1 个请求去查询并写入缓存,其他请求重试取缓存读取
优势:
1、可以减少同时发起请求的并发连接
2、应用级别支持,实现相对简单
不足:
1、未获取到锁的线程会阻塞,不适合缓存写入等逻辑复杂,用时较长的情况
方案三 查询数据库并写入缓存的操作请求需要获取到分布式锁
优势:
1、到数据库的并发请求最少
不足:
1、需要引入分布式锁操作
2、未获取到锁的请求需要定时重试或返回降级内容
版权声明: 本文为 InfoQ 作者【Skysper】的原创文章。
原文链接:【http://xie.infoq.cn/article/2a33767ca3a0b0704f8544a5d】。文章转载请联系作者。
评论