缓存穿透、缓存雪崩和缓存击穿的区别及解决方案

1、缓存穿透

⼤量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这⼀层。

解决方案

  1. 缓存⽆效 key,并设置过期时间,避免占用大量空间。
  2. 设置 key 的规则:表名:列名:主键名:主键值
  3. 参数校验。
  4. 布隆过滤器。

布隆过滤器 底层使用 bit 数组存储数据,该数组中的元素默认值是0。

布隆过滤器第一次初始化的时候,会把数据库中所有已存在的 key,经过一些列的 hash 算法(比如:三次 hash 算法)计算,每个 key 都会计算出多个位置,然后把这些位置上的元素值设置成1。

缓存穿透、缓存雪崩和缓存击穿的区别及解决方案_第1张图片

之后,有用户 key 请求过来的时候,再用相同的 hash 算法计算位置。

  • 如果多个位置中的元素值都是1,则说明该 key 在数据库中已存在。这时允许继续往后面操作。

  • 如果有1个以上的位置上的元素值是0,则说明该 key 在数据库中不存在。这时可以拒绝该请求,而直接返回。

使用布隆过滤器确实可以解决缓存穿透问题,但同时也带来了两个问题:

  1. 存在误判的情况。(如果想减少误判率,可以适当增加hash函数)
  2. 存在数据更新问题。(如果数据库中的数据更新了,需要同步更新布隆过滤器。但它跟数据库是两个数据源,就可能存在数据不一致的情况。)

布隆过滤器要看实际业务场景再决定是否使用,它帮我们解决了缓存穿透问题,但同时了带来了新的问题。

2、缓存雪崩

缓存同⼀时间⼤⾯积的失效,所以,后⾯的请求都会落到数据库上,造成数据库短时间内承受⼤量请求⽽崩掉。

解决方案

  • 事前:尽量保证整个 redis 集群的⾼可⽤性,发现机器宕机尽快补上。选择合适的内存淘汰策略。
  • 事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 崩掉。随机设置缓存数据的过期时间,防止同一时间大量数据过期现象发生。热点数据不设置过期时间,永不过期。
  • 事后:利⽤ redis 持久化机制保存的数据尽快恢复缓存。

缓存穿透、缓存雪崩和缓存击穿的区别及解决方案_第2张图片

3、缓存击穿

缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。

缓存雪崩缓存击穿 的区别?

缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。

解决方案

  1. 加互斥锁,再把从数据库中查询到的结果,又重新放入缓存中。
  2. 定时任务给指定 key 自动续期。
  3. 热点数据不设置过期时间,永不过期。

你可能感兴趣的:(实践,缓存,redis,java)