在高并发和安全压力下,解决redis缓存穿透、缓存雪崩、缓存击穿问题

一、缓存穿透、缓存雪崩、缓存击穿

1、缓存穿透:查询一个不存在的数据
利用不存在的key请求网站,由于缓存服务器不命中。如果其一直请求,则每次都一直去查mysql数据库,这样就使我们的缓存服务器失去了意义。
每次都绕开redis缓存服务器而直接访问到MySQL服务器,在流量大的时候,db就直接挂掉。
利用不存在的key频繁攻击我们的应用,这样的漏洞。
解决方案:空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

pmsSkuInfo = getSkuByIdFromDb(skuId);  //建立redis缓存服务器,就是为了保护这行代码:查询数据库的操作
if(pmsSkuInfo!=null) {
    //mysql查询结果存入redis
    jedis.set("sku:"+skuId+":info", JSON.toJSONString(pmsSkuInfo));    //把java对象 转为 json字符串

}else {  //mysql查询结果为null,防止缓存穿透!!!!

    //把这个不存在的skuId设为:空值json字符串null,并存到redis服务器中。
    jedis.setex("sku:"+skuId+":info",60*3, JSON.toJSONString(""));
    //seconds是秒。3分钟内再有请求这skuId,就直接返回一个空的对象给前端(没有任何信息)。不再执行查询数据库操作
}

2、缓存雪崩:雪崩是很多key集体失效
设置缓存时,采用了相同的过期时间,导致缓存某一时刻同时失效,请求全部怼到数据库,导致数据库压力过重雪崩
解决方案:设置不同的缓存失效时间,比如1-5分钟设置随机失效时间

3、缓存击穿:击穿是一个热点key失效
某个热点key在高并发访问的时候,突然失效(过期或者突发事件编译出错等),导致大量的并发请求怼到了mysql数据库的情况
解决方案:重点这里!采用分布式锁。

二、解决热点key缓存击穿的问题

(1)第1种分布式锁:redis自带一个分布式锁:set px nx

你的redis缓存服务器已经宕机了,在服务器重启过程。
就由其他的redis服务器的nx来实现分布式锁,限制用户数量访问数据库

//设置分布式锁,防止缓存击穿!!!
String ok = jedis.set("sku:" + skuId + ":lock", "1", "nx", "px", 10);
if(StringUtils.isNotBlank(ok)&&ok.equals("ok")){ 
 //设置锁返回ok成功,允许这位用户访问数据库,10秒后过期时间,再允许下一位访问
//这里是访问数据库的代码,省略。。。。看上一篇文档
}else {  //设置锁不成功,自旋(设置该线程睡眠几秒,再重新尝试访问本方法)

    try {
        Thread.sleep(3000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    return getSkuById(skuId);   //这里要return返回这个方法重新访问,同一条线程!!
                                //不加return,则创建一条新的线程,原来的线程还是访问不到,即原来的线程成了一条孤儿线程!
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(2)第二种分布式锁:redisson框架,一个redis的带有juc的lock功能的客户端的实现(既有jedis的功能,又有juc的锁功能)

jedis在集群当中没有juc多线程锁的机制,单jedis是做不到同时访问redis服务器

juc锁的功能:实现用户1、2、3…等可以同时访问redis服务器

两种分布式锁的区别:
redisson框架的解决方法是 在客户端解决问题
redis自带的分布式锁是 在redis服务器解决问题

在这里插入图片描述

三、方法自旋

错误的自旋代码。本来是A线程访问该访问,这里不加return,则创建新的一条B线程。由B线程重新访问本方法,A线程则成了孤儿线程!!!永远无法正常访问,这是java的基础知识了。
所以自旋本方法一定要加return!!!!
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值