缓存击穿、缓存穿透、缓存雪崩、缓存一致性
缓存击穿
缓存中某个热点数据因为过期或被删除而突然失效,同时大量请求要获取该数据,因为没有在缓存中找到数据,所以在数据重新载入缓存之前,大量查询请求直接来到数据库,引起数据库压力瞬间增大,可能导致数据库大量请求阻塞甚至崩溃
解决方案:
1、设置缓存永不过期
2、缓存预热,主动设置一个过期时间,在过期之前进行都缓存更新
3、加互斥锁,线程访问缓存未命中时,获取一把互斥锁,然后进行数据库操作;此时另一线程未命中时,没有拿到锁,等待一段时间后重新查询缓存,拿到了此前线程加载到缓存中的数据。可能会有出现死锁
4、限流,限制请求数量,只能缓解一定压力
缓存雪崩
在某一时间段,缓存集中失效,导致请求全部走数据库,有可能搞垮数据库,使整个服务瘫痪。
使缓存集中失效的原因:
1、redis服务器挂掉了。
2、对缓存数据设置了相对集中的过期时间,导致某时间段内缓存集中失效。
解决方案:
1、离散过期时间:数据过期时间设置的相对分散一些。不要设置相对集中和相同的过期时间
2、缓存预热
3、双级缓存:原始缓存失效,访问备用缓存
4、限流和熔断:只能缓解一定压力
限流(Rate Limiting)
限流是一种控制系统接收的请求数量或处理的操作数量的技术,以确保系统在可承受的负载范围内运行。它的主要目的是防止资源被过度使用,特别是在高流量的情况下。
实现方式:
令牌桶(Token Bucket)算法:这是一种常用的限流算法。系统以固定的速率生成令牌并放入桶中,每个请求需要消耗一个令牌才能被处理。如果桶空了,新的请求就会被拒绝或排队等待。
漏桶(Leaky Bucket)算法:漏桶算法通过固定的速率“漏掉”请求来限流。无论进入的流量有多大,流出的速率始终保持恒定。
计数器:在一个给定的时间窗口内计数请求,当达到预定的限制时,新的请求将被拒绝或延迟处理。
熔断(Circuit Breaking)
熔断是一种自动检测服务故障并阻止故障蔓延的保护机制。当检测到一定量的失败请求时,熔断器会“跳闸”,暂时中断服务。它的主要目的是防止系统在出现问题时进一步恶化。
缓存穿透
查询一个一定不存在的数据,数据在缓存中不存在,同时在数据库中查到的结果为空,因此不会把这个结果放到缓存中,导致每次请求都会进行缓存和数据库的两次查询
解决方案:
1、缓存空对象,即使在数据库中查到结果为空,也将其放到缓存中,但是空值太多会造成性能下降
2、布隆过滤器(添加在数据库和缓存之间):在访问数据值钱通过布隆过滤器快速确定数据是否存在,不存在就跳过查询数据库操作直接返回结果
缓存一致性
确保某个数据更新后缓存和数据库中的数据一致
1、延时双删+消息队列
通过延时双删保证数据一致性,通过消息队列保证延时双删的顺利执行
2、加锁(性能差)