一、Redis的缓存穿透
1.什么是缓存穿透?
缓存穿透是指:客户端请求的数据在缓存中和数据库中都不存在,这时缓存就永远不会生效,这些请求都打到数据库从而导致数据库压力过大。
2.出现缓存穿透的解决方案,以下是常用的两种:
(1)做缓存空对象:
如果一个查询返回的数据为空(不管是数据是否不存在),我们仍然把这个空结果(null)进行缓存,设置空结果的过期时间会很短,最长不超过五分钟。
缓存空对象的优缺点:
优点:实现简单,维护方便
缺点:额外的内存消耗,以及可能造成短期的数据不一致。(如果在做了空缓存之后,我们向数据库中插入了新的数据,而插入的数据正好是之前做了空缓存的数据,此时就会出现短期数据不一致的问题)
(2)使用布隆过滤器:
布隆过滤器(Bloom Filter),它实际上是一个很长的二进制向量(位图)和一系列的随机映射函数(哈希函数),它可以用于检索一个元素是否存在一个集合中,他的优点是空间的查询效率和查询时间都远远超过一般算法,缺点是有一定的误识别率和删除比较困难。
如下是加入布隆过滤器的一个实现流程
使用布隆过滤器的优缺点:
优点:内存占用少,没有多余的key
缺点:实现的过程比较复杂,并且存在误判的可能
二、缓存击穿
1.什么是缓存击穿
** 缓存击穿也叫热点key问题,就是一个被高并发访问并且缓存业务重构复杂的key突然失效了,无数的请求会在瞬间给数据库带来巨大的冲击。**
当缓存的热点key过期后,一个线程来请求数据,查询缓存未命中,然后从数据库中查询然后重新构建缓存数据(需要一定的时间),在缓存数据还没构建完成此时又有大量请求进来去查询数据,缓存中未命中数据,于是后面进来的请求也同步之前请求从数据库中查询数据并构建缓存的这一过程,此时这些请求全部打到数据库中,导致数据库压力变大。
大致如下图:
2.出现缓存击穿的结局方案:
即一个线程得到锁去更新数据的时候,其他线程进来去查询数据的时候需要先去获取锁才能去查询数据库来更新缓存。此时因为已经有线程去更新缓存了,故在多次查询后就可命中缓存中的数据。
(2)设置逻辑过期:
对比以上两种方案优缺点如下:
互斥锁
优点:
没有额外的内存开销
保证了一致性
实现简单
缺点
线程需要等待
可能会有死锁的风险
逻辑过期:
优点:
线程无需等待,性能较好
缺点:
不保证一致性
有额外的内存消耗
实现比较复杂
三、缓存雪崩
1.什么是缓存雪崩:
缓存雪崩是指:在同一时间段大量的缓存key失效或者Redis宕机,这时候大量的请求向数据库请求信息,此时可能就会把数据库压垮。
过程大致如下:
出现缓存雪崩的解决方案常用的有如下:
(1)给不同的key的TTL设置随机值
(2)利用Redis集群提高服务的可用性
(3) 给缓存业务添加限流降级的策略
(4)给业务添加多级缓存