redis击穿,穿透,雪崩以及解决方案「建议收藏」

redis击穿,穿透,雪崩以及解决方案「建议收藏」1击穿:指的是单个key在缓存中查不到,去数据库查询,这样如果数据量不大或者并发不大的话是没有什么问题的。如果数据库数据量大并且是高并发的情况下那么就可能会造成数据库压力过大而崩溃注意:这里指的是单个key发生高并发!!!解决方案:1)通过synchronized+双重检查机制:某个key只让一个线程查询,阻塞其它线程在同步块中,继续判断检查,保证不…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

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

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

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

解决方案:

  1) 通过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;

   }

缺点: 会阻塞其它线程

   2) 设置value永不过期

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

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

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

   3) 使用互斥锁(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;      
          }

}

缺点:

1. 代码复杂度增大

2. 存在死锁的风险

3. 存在线程池阻塞的风险

2 雪崩

雪崩指的是多个key查询并且出现高并发,缓存中失效或者查不到,然后都去db查询,从而导致db压力突然飙升,从而崩溃。

出现原因: 1 key同时失效

                 2 redis本身崩溃了

方案:

  1. 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。(跟击穿的第一个方案类似,但是这样是避免不了其它key去查数据库,只能减少查询的次数)
  2. 可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存
  3. 不同的key,设置不同的过期时间,具体值可以根据业务决定,让缓存失效的时间点尽量均匀
  4. 做二级缓存,或者双缓存策略。A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。(这种方式复杂点)

3 穿透

   一般是出现这种情况是因为恶意频繁查询才会对系统造成很大的问题: key缓存并且数据库不存在,所以每次查询都会查询数据库从而导致数据库崩溃。

解决方案:

          1) 使用布隆过滤器: 热点数据等场景(具体看使用场景)

                

布隆过滤器是什么?

布隆过滤器可以理解为一个不怎么精确的 set 结构,当你使用它的 contains 方法判断某个对象是否存在时,它可能会误判。但是布隆过滤器也不是特别不精确,只要参数设置的合理,它的精确度可以控制的相对足够精确,只会有小小的误判概率。

当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在。打个比方,当它说不认识你时,肯定就不认识;当它说见过你时,可能根本就没见过面,不过因为你的脸跟它认识的人中某脸比较相似 (某些熟脸的系数组合),所以误判以前见过你。

缺点: 1 会存在一定的误判率

          2  对新增加的数据无法进行布隆过滤

          3 数据的key不会频繁的更改

   google 的 gauva 中有布隆过滤的实现

redis击穿,穿透,雪崩以及解决方案「建议收藏」

     BloomFilter的关键在于hash算法的设定和bit数组的大小确定,通过权衡得到一个错误概率可以接受的结果。

     我们设置的容错率越小那么过滤函数也就多,分配的空间也就越大(存放bits),那么误判率也就越小。

2 将击透的key缓存起来,但是时间不能太长,下次进来是直接返回不存在,但是这种情况无法过滤掉动态的key,就是说每次请求进来都是不同额key,这样还是会造成这个问题

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/193823.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • WinSCP连接Ubuntu拒绝访问,SSH访问状态确认

    WinSCP连接Ubuntu拒绝访问,SSH访问状态确认WinSCP连接Ubuntu拒绝访问的问题

  • Windows AD域功能介绍、Windows AD域方案介绍

    Windows AD域功能介绍、Windows AD域方案介绍WindowsAD域功能介绍、WindowsAD域方案介绍功能一、AD域管理https://www.manageengine.cn/products/ad-manager/1、AD域管理通过批量创建和编辑用户帐户,指派管理权限等,简化WindowsAD域的管理。2、批量管理域用户使用CSV文件批量导入用户、编辑用户属性、重置密码、批量迁移用户和用户对象。3、批量创建域用…

  • 操作系统栈溢出检测之ucosII篇[通俗易懂]

    操作系统栈溢出检测之ucosII篇[通俗易懂]操作系统栈溢出检测之uc/osII篇Author              :     DavidLin(林鹏)E-mail               :       linpeng1577@gmail.com                                    linpeng1577@163.com 158820224344@163.co

  • 二代身份证编码规则及校验代码实现

    二代身份证编码规则及校验代码实现本文主要讨论的是二代身份证编码规则及其Java代码实现,下面的校验方式还不是特别严谨,由于只校验了前两位的省份信息,中间六位的出生日期信息和最后一位的校验码信息,故对于部分不满足要求的证件号码刚好同时满足了这里提到的几个条件,也会被判定为是合法的证件号码…1二代身份证号码编码规则1.1编码格式1999年我国颁发了第二代居民身份证号,公民身份号码为18位,且终身不变。居民身份证格式如:ABCDEF

  • 逻辑删除还是物理删除

    逻辑删除还是物理删除看到标题,有的童鞋心中暗想“数据删除有什么可提的呢?不就是执行个delete语句吗?有什么难的呀?”其实呢数据删除没有你想的这么简单,一般情况下公司会明确的要求数据只能逻辑删除,不能物理删除。那什么优势逻辑删除,什么又是物理删除呢?物理删除就是我们之前常用的DELETE、TRANCATE、DROP语句删除数据,不管你用哪种方式,都是将数据从硬盘上抹除,这样数据表的体积就变小了,数据的读写性能就提上去了。有个共识InnoDB引擎的数据表记录一旦超过2000万,它的读写性能就很差,我们用物理删除能缩小表

  • Redis布隆过滤器原理与实践

    Redis布隆过滤器原理与实践背景在高并发请求时,业务数据一般会对数据进行缓存,提高系统并发量,因为磁盘IO和网络IO相对于内存IO的成百上千倍的性能劣势。做个简单计算,如果我们需要某个数据,该数据从数据库磁盘读出来需要0.1s,从交换机传过来需要0.05s,那么每个请求完成最少0.15s(当然,事实上磁盘和网络IO也没有这么慢,这里只是举例),该数据库服务器每秒只能响应67个请求;而如果该数据存在于本机内存里,读出来只需要10us,那么每秒钟能够响应100,000个请求。通过将高频使用的数据存在离cpu更近的位置,以减少数据传

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号