Redis 缓存穿透、缓存击穿、缓存雪崩和解决方案

设计一个缓存系统,不得不要考虑的问题就是:缓存穿透、缓存击穿与失效时的雪崩效应。

缓存穿透

原因

缓存穿透:是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。

解决方案

解决穿透一般有三种方法:

  1. 如果是非法请求,可以在API入口,对参数进行校验,过滤非法值。
  2. 如果查询数据库为空,可以给缓存设置个空值,或者默认值。但是如有有写请求进来的话,需要更新缓存哈,以保证缓存一致性,同时,最后给缓存设置适当的过期时间。(业务上比较常用,简单有效)
  3. 使用 布隆过滤器 快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。

布隆过滤器原理:它由初始值为 0 的位图数组和 N 个哈希函数组成。一个对一个 key 进行 N 个 hash 算法获取 N 个值,在比特数组中将这 N 个值散列后设定为 1,然后查的时候如果特定的这几个位置都为 1,那么布隆过滤器判断该 key 存在。

缓存雪崩

原因

缓存雪奔:是指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至 down 机。

当然,Redis 故障宕机也可能引起缓存雪奔。

解决方案
  1. 考虑用加锁或者队列的方式保证缓存的单线程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。
  2. 可以给缓存设置过期时间时加上一个随机值时间,使得每个 key 的过期时间分布开来,不会集中在同一时刻失效。
  3. Redis 高可用集群。

缓存击穿

原因

缓存击穿:是指热点 key 在某个时间点过期的时候,而恰好在这个时间点对这个 Key 有大量的并发请求过来,从而大量的请求打到数据库,进而给数据库带来压力。

解决方案
  1. 使用互斥锁方案。缓存失效时,不是立即去加载 db 数据,而是先使用某些带成功返回的原子操作命令,如 (Redis的setnx) 去操作,成功则再去加载 db 数据库数据和设置缓存,否则就去重试获取缓存。
  2. “永不过期”,是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。
----------本文结束感谢您的阅读----------
xiaolong wechat
一只程序猿对世界的不完全理解