Redis缓存三大问题

缓存三大问题

​ 我们都知道,Redis的Key都存在一个ttl(time to live)过期时间,Redis默认的是永不过期。Redis作为缓存,一方面可以提升速度,但也会带来三大常见的缓存问题:缓存穿透缓存击穿缓存雪崩

​ Redis作为缓存使用,一般为后端的缓存,主要对MySQL中的热点数据作缓存,减少对数据库的访问,因为MySQL查询效率远不及Redis。一般缓存的使用方式如下图所示:

在这里插入图片描述

缓存运行原理:当业务系统发送数据查询请求时,首先会在缓存中查看数据是否存在,如果存在,从缓存中获取数据并返回;否则,进入数据库中查询,找到数据后再返回。

1 、缓存穿透

概念:业务系统查询缓存和数据库中都不存在的数据。当通过接口发送数据查询请求,请求的数据在缓存中没有,转而所有请求转向数据库,但是数据库中也不存在该数据。此时,缓存起不到保护数据库的作用,就像被穿透了一样,这种现象称为缓存穿透。

危害:如果黑客大量发起不存在的数据请求,海量的请求转向数据库,数据库承受不了流量洪峰,数据库压力剧增,可能导致系统瘫痪。在目前的业务系统中,比较脆弱的就是IO部分。

解决方案:

  • 前端验证。对于接口的请求参数进行前端校验,验证合格后再发起后端数据查询请求。
//验证表单是否为空,若为空则将焦点聚焦在input表单上,否则表单通过,登录成功
function check(form){
  var accountName = $("#accountName"),$password = $("#password");
  var accountName = accountName.val(),password = $password.val();
  if(!accountName || accountName == ""){
    showMsg("请输入用户名");
    form.accountName.focus ();
    return false;
  }
  if(!password || password == ""){
    showMsg("请输入密码");
    form.password.focus ();
    return false;
  }
//这里为用ajax获取用户信息并进行验证,如果账户密码不匹配则登录失败,如不需要验证用户信息,这段可不写
 $.ajax({
    url : systemURL,// 获取自己系统后台用户信息接口
    data :{"password":password,"accountName":accountName},
    type : "GET",
    dataType: "json",
    success : function(data) {
      if (data){
        if (data.code == "1111") { //判断返回值,这里根据的业务内容可做调整
            setTimeout(function () {//做延时以便显示登录状态值
              showMsg("正在登录中...");
              console.log(data);
              window.location.href = url;//指向登录的页面地址
            },100)
          } else {
            showMsg(data.message);//显示登录失败的原因
            return false;
          }
        }
      },
      error : function(data){
        showMsg(data.message);
      }
  });
}

//错误信息提醒
function showMsg(msg){
  $("#CheckMsg").text(msg);
}

//监听回车键提交
$(function(){
  document.onkeydown=keyDownSearch;
  function keyDownSearch(e) {
    // 兼容FF和IE和Opera
    var theEvent = e || window.event;
    var code = theEvent.keyCode || theEvent.which || theEvent.charCode;
    if (code == 13) {
      $('#submit').click();//具体处理函数
      return false;
    }
    return true;
  }
});
  • 缓存空值。之所以会发生缓存穿透,是因为缓存中不存在这些空数据的key,才会导致所有请求转向数据库。如果当数据库返回为空时,把这些空值对应的key缓存到Redis,并合理设置过期时间。

在这里插入图片描述

  • 使用布隆过滤器。布隆过滤器可以用于检索一个元素是否在一个集合中,它的优点是空间效率和查询时间比一般的算法要好得多。当业务系统发出查询请求的时候,首先去布隆过滤器中查询该key是否存在。如果不存在,则说明数据库中也不存在该数据,因此不需要查询,直接返回null。如果存在,则继续执行后续的流程,先前往Redis缓存中查询,缓存中没有的话再前往数据库中的查询。

在这里插入图片描述

方案选择:

(1)对于黑客的恶意攻击,查询的key值往往不同,而且数据量巨大。使用缓存空值的方法不大可取,可以使用布隆过滤器进行海量请求的过滤。

(2)如果查询的空数据,key值重复率高,可以选择缓存空值的方法。

2、 缓存击穿

概念:某个热点key存在与Redis缓存中,在它过期的一瞬间,大量查询该key的请求转向数据库,造成瞬间数据库的数据达到洪峰,压力剧增。这时缓存像是被击穿了一样,称为缓存击穿现象。

危害:海量的请求转向数据库,可能导致数据库服务器宕机,整个应用系统不能正常工作。

解决方案:

  • 使用互斥锁。当业务系统发出查询请求时,这时Redis缓存中对应地key失效了,会转向数据库查询,数据库查询完成后,查询完成后也会造成缓存重建重复。加上互斥锁不会发生这种现象,当第一个数据库查询请求发起后,就将缓存中该Key对应的数据上锁;此时到达缓存的其他查询请求将无法查询该字段,从而被阻塞。当第一个请求完成数据库查询,并将数据更新值缓存后,释放锁;此时其他被阻塞的查询请求将可以直接从缓存中查到该数据。但是,这样其他线程会被阻塞,导致系统的吞吐量下降。

在这里插入图片描述

  • 设置缓存数据用不过期。这里的不过期可以是设置永不过期,或者是在数据快要过期时,有异步的线程去构建缓存的热点数据,达到永不过期的效果。
  • 设置接口限流与熔断,降级。在业务系统中,重要的数据查询接口,一定要做好相应的限流措施,防止用户恶意访问,同时要进行降级准备。当接口中的某些服务不可用时,进行熔断。

方案选择:

(1)互斥锁方案,完全依赖于第一个线程进行缓存重建,其余线程查询新缓存中的数据。一旦构建缓存中过程出现问题,会出现线程死锁和线程池阻塞的风险。而且,这种方案会降低业务系统的吞吐量。

(2)设置永不过期方案,可能会出现问题,实际上已经不存在热点 key 产生的一系列危害,会存在数据不一致的情况,同时代码复杂度会增大。

3 、缓存雪崩

概念:大量的热点数据在同一时间过期,导致Redis缓存在同一时刻集体失效。同一时刻,对不同的过期key进行访问,引起雪崩的现象,造成瞬时数据库请求量大,压力骤增,数据库可能崩溃。
在这里插入图片描述

解决方案:

  • 优化缓存过期时间。将热点数据的过期时间打散。雪崩的原因,在于同一时刻,大量热点数据同时过期,我们只要给热点数据设置过期时间加个随机值,就能解决这个问题。
  • 保持Redis缓存层的高可用性。使用Redis 哨兵模式或者Redis 集群部署方式,即便个别Redis 节点宕机,整个缓存层依然可以使用。
  • 设置缓存数据用不过期。与防止缓存击穿的方案一致,这里的不过期可以是设置永不过期,或者是在数据快要过期时,有异步的线程去构建缓存的热点数据,达到永不过期的效果。
  • 使用互斥锁重建缓存。根据 key 去缓存层查询数据,当缓存层为命中时,对 key 加锁,然后从存储层查询数据,将数据写入缓存层,最后释放锁。若其他线程发现获取锁失败,则让线程休眠一段时间后重试。
  • 使用限流和降级组件。假如有一个资源不可用,可能会造成所有线程在获取这个资源时异常,造成整个系统不可用,可以降级补充热点数据,降级在高并发系统中是非常正常的。Hystrix是一款开源的“防雪崩工具”,它通过 熔断、降级、限流三个手段来降低雪崩发生后的损失。

同一时间过期,导致Redis缓存在同一时刻集体失效。同一时刻,对不同的过期key进行访问,引起雪崩的现象,造成瞬时数据库请求量大,压力骤增,数据库可能崩溃。

解决方案:

  • 优化缓存过期时间。将热点数据的过期时间打散。雪崩的原因,在于同一时刻,大量热点数据同时过期,我们只要给热点数据设置过期时间加个随机值,就能解决这个问题。
  • 保持Redis缓存层的高可用性。使用Redis 哨兵模式或者Redis 集群部署方式,即便个别Redis 节点宕机,整个缓存层依然可以使用。
  • 设置缓存数据用不过期。与防止缓存击穿的方案一致,这里的不过期可以是设置永不过期,或者是在数据快要过期时,有异步的线程去构建缓存的热点数据,达到永不过期的效果。
  • 使用互斥锁重建缓存。根据 key 去缓存层查询数据,当缓存层为命中时,对 key 加锁,然后从存储层查询数据,将数据写入缓存层,最后释放锁。若其他线程发现获取锁失败,则让线程休眠一段时间后重试。
  • 使用限流和降级组件。假如有一个资源不可用,可能会造成所有线程在获取这个资源时异常,造成整个系统不可用,可以降级补充热点数据,降级在高并发系统中是非常正常的。Hystrix是一款开源的“防雪崩工具”,它通过 熔断、降级、限流三个手段来降低雪崩发生后的损失。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值