16 redis-穿透、雪崩、热点

 

Redis做缓存是最常见的应用场景。客户端请求在缓存层命中就直接返回,如果没命中就去查询数据库,再写入到redis,然后再返回到客户端。流程如下:

 

 

在这个过程中会有如下常见问题

1 穿透

穿透:频繁查询一个不存在的数据,由于缓存不命中,每次都要查询持久层。从而失去缓存的意义。

示例说明:比如数据库表和缓存中的id都是正整数,而程序传入了 -1,那么每次都会先查缓存,再查数据库。

解决办法

  • 缓存空值,如果持久层查询不到,就在redis中缓存一个空值,每次访问从redis中直接返回一个null,并设定一个有效时间。
  • 使用布隆过滤器,布隆过滤器的巨大用处就是,能够迅速判断一个元素是否在一个集合中,其结构是一个bit数组。使用布隆过滤器将缓存的key存一下,每次访问时先从布隆过滤器判断是否为0,如果为0直接返回null。

2 雪崩

雪崩:缓存的key大量失效(过期)的时候,引发大量查询数据库,而对数据库CPU和内存造成巨大压力,严重的会造成数据库

解决办法

  • 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
  • 可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存
  • 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀
  • 做二级缓存,或者双缓存策略。A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。

3 热点KEY

热点key:某个key访问非常频繁,当key失效的时候有打量线程来构建缓存,导致负载增加,系统崩溃。

解决办法:

  • 使用锁,单机用synchronized,lock等,分布式用分布式锁。
  • 缓存过期时间不设置,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存。
  • 在value设置一个比过期时间t0小的过期时间值t1,当t1过期的时候,延长t1并做更新缓存操作。
posted @ 2019-04-21 15:28  java小工匠  阅读(362)  评论(0编辑  收藏  举报