redis击穿现象如何防止

 更新时间:2023年07月27日 10:14:46   作者:逆流°只是风景-bjhxcc  
本文主要介绍了redis击穿现象如何防止,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

背景

大家都知道,计算机的瓶颈之一就是IO,为了解决内存与磁盘速度不匹配的问题,产生了缓存,将一些热点数据放在内存中,随用随取,降低连接到数据库的请求链接,避免数据库挂掉。需要注意的是,无论是击穿还是后面谈到的穿透与雪崩,都是在高并发前提下 ,当缓存中某一个热点key失效。

击穿

指的是单个key在缓存中查不到,去数据库查询,这样如果数据量不大或者并发不大的话是没有什么问题的。

如果数据库数据量大并且是高并发的情况下那么就可能会造成数据库压力过大而崩溃

注意: 这里指的是单个key发生高并发!!!

案例

这里要注意的是这是某一个热点key过期失效和后面介绍缓存雪崩是有区别的。比如淘宝双十一,对于某个特价热门的商品信息,缓存在Redis中,刚好0点,这个商品信息在Redis中过期查不到了,这时候大量的用户又同时正好访问这个商品,就会造成大量的请求同时到达数据库。

解决方案

通过synchronized+双重检查机制

某个key只让一个线程查询,阻塞其它线程

在同步块中,继续判断检查,保证不存在,才去查DB。

例如:

 private static volaite Object lockHelp=new Object();
   public String getValue(String key){
     String value=redis.get(key,String.class);
     if(value=="null"||value==null||StringUtils.isBlank(value){
         synchronized(lockHelp){
                value=redis.get(key,String.class);
                 if(value=="null"||value==null||StringUtils.isBlank(value){
                     value=db.query(key);
                      redis.set(key,value,1000);
                  }
            }
           }    
        return value;
   }

缺点: 会阻塞其它线程

设置value永不过期(设置热点数据永不过期)

这种方式可以说是最可靠的,最安全的但是占空间,内存消耗大,并且不能保持数据最新 这个需要根据具体的业务逻辑来做

个人觉得如果要保持数据最新不放这么试试,仅供参考:

起个定时任务或者利用TimerTask 做定时,每个一段时间多这些值进行数据库查询更新一次缓存,当然前提时不会给数据库造成压力过大(这个很重要)

使用互斥锁(mutex key)

业界比较常用的做法,是使用mutex。简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。

SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。在redis2.6.1之前版本未实现setnx的过期时间,所以这里给出两种版本代码参考:

public String get(key) {
      String value = redis.get(key);
      if (value == null) { //代表缓存值过期
          //设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
          if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功
               value = db.get(key);
                      redis.set(key, value, expire_secs);
                      redis.del(key_mutex);
                     return value;
              } else {  //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
                      sleep(10);
                      get(key);  //重试
              }
          } else {
              return value;      
          }
}

缺点:

  • 代码复杂度增大
  • 存在死锁的风险
  • 存在线程池阻塞的风险

击穿与雪崩的不同在于缓存key失效的量级上。击穿是对于单个key值的缓存失效过期,雪崩则是大面积key同时失效。

到此这篇关于redis击穿现象如何防止的文章就介绍到这了,更多相关redis 击穿内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 浅谈Redis常见延迟问题定位与分析

    浅谈Redis常见延迟问题定位与分析

    大部分时候,redis延迟很低,但是在某些时刻,有些redis实例会出现很高的响应延时,本文主要介绍了浅谈Redis常见延迟问题定位与分析,具有一定的参考价值,感兴趣的可以了解一下
    2022-06-06
  • 手把手教你使用redis实现排行榜功能

    手把手教你使用redis实现排行榜功能

    使用Redis中有序集合的特性来实现排行榜是又好又快的选择,一般排行榜都是有实效性的,比如“用户积分榜”,下面这篇文章主要给大家介绍了关于使用redis实现排行榜功能的相关资料,需要的朋友可以参考下
    2023-04-04
  • Redis中主键失效的原理及实现机制剖析

    Redis中主键失效的原理及实现机制剖析

    这篇文章主要介绍了Redis中主键失效的原理及实现机制剖析,本文讲解了失效时间的控制、失效的内部实现、Memcached 删除失效主键的方法与 Redis 有何异同、Redis 的主键失效机制会不会影响系统性能等内容,需要的朋友可以参考下
    2015-06-06
  • Redis持久化深入详解

    Redis持久化深入详解

    这篇文章主要介绍了Redis持久化深入详解,讲解的还是比较详细的,有感兴趣的同学可以学习下
    2021-03-03
  • Redis 哨兵机制及配置实现

    Redis 哨兵机制及配置实现

    本文主要介绍了Redis 哨兵机制及配置实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • Redis实现布隆过滤器的方法及原理

    Redis实现布隆过滤器的方法及原理

    布隆过滤器优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。本文将介绍布隆过滤器的原理以及Redis如何实现布隆过滤器,感兴趣的朋友跟随小编一起看看吧
    2019-12-12
  • redis replication环形缓冲区算法详解

    redis replication环形缓冲区算法详解

    这篇文章主要介绍了redis replication环形缓冲区算法的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • Redis整合Spring结合使用缓存实例

    Redis整合Spring结合使用缓存实例

    这篇文章主要介绍了Redis整合Spring结合使用缓存实例,介绍了如何在Spring中配置redis,并通过Spring中AOP的思想,将缓存的方法切入到有需要进入缓存的类或方法前面。需要的朋友可以参考下
    2015-12-12
  • 关于Redis的内存淘汰策略详解

    关于Redis的内存淘汰策略详解

    当内存空间使用达到限制时,Redis 会根据配置策略来选择不同处理方式,要么返回 errors,要么按照不同的策略算法来清除一些旧数据,达到回收内存的目的,这就是 Redis 的内存淘汰,有些文章中,内存淘汰也叫缓存回收,需要的朋友可以参考下
    2023-05-05
  • 基于Redis实现消息队列的示例代码

    基于Redis实现消息队列的示例代码

    消息队列在分布式系统中非常重要,能够有效解耦系统的各个模块,提供异步处理能力和缓冲能力,本文介绍了基于Redis实现消息队列的示例代码,感兴趣的可以了解一下
    2025-04-04

最新评论