当前位置:   article > 正文

redis详解之缓存雪崩、穿透、击穿的原因和解决方案_c#中redis的血崩

c#中redis的血崩

一、缓存雪崩

1、产生原因:

(1)redis挂掉了,请求全部走数据库
(2)对缓存数据设置相同的过期时间,导致某段时间内缓存失效,请求全部走数据库。
(3)缓存雪崩如果发生了,很可能就把我们的数据库搞垮,导致整个服务瘫痪!

 2、解决方法: 

(1)在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。
(2)对于“Redis挂掉了,请求全部走数据库”这种情况,我们可以有以下的思路:
事发前:实现Redis的高可用(主从架构+Sentinel(哨兵) 或者Redis Cluster(集群)),尽量避免                Redis挂掉这种情况发生。
事发中:万一Redis真的挂了,我们可以设置本地缓存(ehcache)+限流(hystrix),尽量避免我们的                  数据库被干掉(起码能保证我们的服务还是能正常工作的)
事发后:redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。

二、缓存穿透

1、产生原因:

(1)请求的数据在缓存大量不命中,导致请求走数据库。
(2)缓存穿透如果发生了,也可能把我们的数据库搞垮,导致整个服务瘫痪!

 2、解决方法:

(1)由于请求的参数是不合法的(每次都请求不存在的参数),于是我们可以使用布隆过滤器或者压缩filter提前拦截,不合法就不让这个请求到数据库层!学习BloomFilter点这里
(2)当我们从数据库找不到的时候,我们也将这个空对象设置到缓存里边去。下次再请求的时候,就可以从缓存里边获取了。这种情况我们一般会将空对象设置一个较短的过期时间。

三、缓存击穿

1、产生原因:

缓存击穿,就是说某个 key 非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个 key 在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库

2、解决办法:

(1)设置key永不过期,或者快过期时,通过另一个异步线程重新设置key;
(2)使用互斥锁的方式;

  1. static Lock reenLock = new ReentrantLock();
  2. public List<String> getData04() throws InterruptedException {
  3. List<String> result = new ArrayList<String>();
  4. // 从缓存读取数据
  5. result = getDataFromCache();
  6. if (result.isEmpty()) {
  7. if (reenLock.tryLock()) {
  8. try {
  9. System.out.println("我拿到锁了,从DB获取数据库后写入缓存");
  10. // 从数据库查询数据
  11. result = getDataFromDB();
  12. // 将查询到的数据写入缓存
  13. setDataToCache(result);
  14. } finally {
  15. reenLock.unlock();// 释放锁
  16. }
  17. } else {
  18. result = getDataFromCache();// 先查一下缓存
  19. if (result.isEmpty()) {
  20. System.out.println("我没拿到锁,缓存也没数据,先小憩一下");
  21. Thread.sleep(100);// 小憩一会儿
  22. return getData04();// 重试
  23. }
  24. }
  25. }
  26. return result;
  27. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小惠珠哦/article/detail/915986
推荐阅读
相关标签
  

闽ICP备14008679号