1. 缓存穿透
缓存穿透是指查询一个缓存和数据库不存在的数据
。这种情况下,请求肯定会打到数据库,就可能导致数据库宕机。
解决这个问题有两种方法:
- 缓存空查询,但是这样会占用额外的空间
- 验证过滤,例如布隆过滤器
布隆过滤器
布隆过滤器是进行相对准确的存在性验证的高效且节省空间的做法,其底层原理是经过多层的哈希过滤。
简单的来说,我们维护一个哈希数组,对于所有存在的key值,会进行遍历,对每个key值都是用N个hash函数计算其会投射到的位置,这样我们仅能得到一个01数组的过滤器了。
当一个请求过来后,我们会使用N个hash函数分别计算请求的key会映射到数组的哪一位,只有每一位都全部通过,才允许请求通过。
经过上面的步骤,我们可以做到只要存在的key值一定能通过,但是不排除会有一小部分不存在的key通过过滤器的情况。
但是我们可以通过调整数组长度L以及hash函数的个数N来改变通过准确率的期望值,具体的数学推理过程大家感兴趣的可以再深入学习。
2. 缓存击穿
缓存击穿,是指缓存中没有但数据库中有的热点key
在短时间被大量访问。
解决这个问题有三种方法:
- 设置热点key不过期
- 加分布式锁
- 限流
3. 缓存雪崩
缓存雪崩是指在某一时间段缓存集中失效
,导致请求全部走数据库,引起数据库压宕机。
解决这个问题,可以设置随机过期时间。
4. 缓存一致性问题
解决数据库与缓存不一致问题的主流做法是延迟双删。
延迟双删的流程如下:
- 更新操作熟悉删除Redis缓存
- 之后更新数据库中的数据
- 更新操作休眠一段时间
- 更新操作再次删除Redis缓存
下面我们逐步来解析每一步操作的意义:
- 第一次删除Redis缓存:这是为了防止更新操作在更新MySQL数据库时,有读请求读到Redis中的脏数据。
- 再次删除Redis缓存:这是啥为了防止更新操作在第一次删除Redis缓存后,有读请求优先于更新请求到达MySQL,再次读取脏数据到Redis缓存。
- 休眠一段时间:这是为了防止更新操作在第一次删除Redis缓存后,有读请求优先于更新请求到达MySQL,但是晚于更新操作再次删除Redis缓存,导致Redis缓存被再次更新成脏数据。