有三类基本问题
- 缓存穿透;
- 缓存击穿;
- 缓存雪崩
缓存穿透(Cache Penetration)
定义
缓存穿透是指请求的数据在缓存和底层数据库中都不存在,导致每次请求都会绕过缓存直接访问数据库,使数据库承受过大压力
发生原因
- 查询不存在的数据
- 恶意攻击(如发送大量ID为-1的请求)
- 缓存设计不当,未缓存空结果2
解决方法
-
布隆过滤器:快速判断请求的数据是否存在
-
缓存空结果:为不存在的数据设置空缓存值,并给予较短的TTL
缓存击穿(Cache Breakdown/Stampede)
定义
缓存击穿指的是某个热点数据缓存过期的同时,大量请求并发访问该数据,导致这些请求绕过缓存直接访问数据库,对数据库造成瞬时压力13。
发生原因
- 热点数据的缓存恰好过期
- 同时有大量请求访问这个热点数据
解决方法
- 互斥锁:第一个请求获取锁并更新缓存,其他请求等待
- 热点数据预热:定期刷新热点数据缓存
- 热点数据不设置过期时间,或者设置一个比较长的时间。
缓存雪崩(Cache Avalanche)
定义
缓存雪崩是指大量缓存同时失效或缓存服务器宕机,导致大量请求直接访问数据库,使数据库被巨大压力压垮,引发系统级联故障
发生原因
- Redis服务器宕机
- 大量缓存在同一时间过期
- 重启后面对堆积的请求,可能再次导致系统崩溃
解决方法
- 随机过期时间:设置不同的缓存 TTL,避免同时过期
- Redis 高可用架构:使用 Redis 集群或哨兵模式
- 熔断机制:当检测到缓存服务异常时,暂时阻断对数据库的请求,返回降级结果
- 服务降级:当检测到系统出现缓存雪崩的迹象时,对一些非核心业务进行服务降级,暂时关闭或限制部分不重要的业务功能,减少对数据库的请求压力,保证核心业务的正常运行。
布隆过滤器详解
什么是布隆过滤器?
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,由Burton Howard Bloom在1970年提出。它用于快速判断一个元素是否可能存在于集合中,具有极低的内存占用和常量级的查询时间复杂度12。
关键特点是:布隆过滤器可能会告诉你一个不在集合中的元素误判为存在(称为”假阳性”),但绝不会将一个存在于集合中的元素误判为不存在(不会有”假阴性”)。用专业术语说就是:可能有假阳性,但绝不会有假阴性。
工作原理
布隆过滤器的核心结构非常简单:一个很长的位数组(bit array)和多个哈希函数
布隆过滤器的数学原理
布隆过滤器的假阳性率与以下因素相关1:
- m: 位数组大小
- k: 使用的哈希函数数量
- n: 预计插入的元素数量
假阳性率计算公式:(1 - e^(-kn/m))
理想情况下,当 k = (m/n)ln(2) 时,假阳性率最小。
布隆过滤器的优点
- 空间效率极高:每个元素只需要几个比特位,而不是存储元素本身5
- 查询时间复杂度O(k):k是哈希函数数量,通常是个小常数
- 插入时间复杂度O(k):同样是哈希函数数量
- 可以处理大规模数据集:即使有数十亿元素,内存占用也很小
- 支持并行操作:不同元素的插入和查询可以并行化1
布隆过滤器的局限性
- 不支持删除操作:标准布隆过滤器无法安全删除元素(但有变种如计数布隆过滤器可以支持)
- 存在假阳性:可能误报元素存在,误报率取决于位数组大小、元素数量和哈希函数数量
- 无法获取具体元素:只能判断成员资格,不能列举成员