redis击穿--互斥锁代码实践

本文介绍在高并发秒杀场景中,如何利用Redis互斥锁防止数据库因key过期而被大量请求击穿的问题。通过自定义keyvalue并使用setNXpx指令,实现对过期key的有效管理,保护后端数据库免受瞬时大流量冲击。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先,击穿指的就是 在某件商品参加秒杀这种对一个key大流量的进行访问时(当然是redis了),忽然,这个key过期了,你的DB必崩!
如何解决?
使用互斥锁!思路就是自定义一个key value,使用 set NX px 1000 (1秒)
语句,当redis中的key过期了也不用怕怕了。他也打不死你的DB,因为你在获取DB前,先进行了

String lockKey  = jedis.set(skuLockKey, "OK", "NX", "PX", ManageConst.SKULOCK_EXPIRE_PX);
                //set  sku:1001:info   ok    nx  px  10000
                //      k           随意的v           十秒
                if ("OK".equals(lockKey)){
                    System.out.println("获取锁!");
                    到这里!别的线程就不会进来了!!!
                    进来的这个进行,获取DB然后 爱放回reids   OK了!
 @Override
    public SkuInfo getSkuInfo(String skuId) {
        SkuInfo skuInfo = null;
    try{
        Jedis jedis = redisUtil.getJedis();
        // 定义key
        String skuInfoKey = ManageConst.SKUKEY_PREFIX+skuId+ManageConst.SKUKEY_SUFFIX; //key= sku:skuId:info

        String skuJson = jedis.get(skuInfoKey);

        if (skuJson==null || skuJson.length()==0){
            // 没有数据 ,需要加锁!取出完数据,还要放入缓存中,下次直接从缓存中取得即可!
            System.out.println("没有命中缓存");
            // 定义key user:userId::lock
            String skuLockKey=ManageConst.SKUKEY_PREFIX+skuId+ManageConst.SKULOCK_SUFFIX;
            // 生成锁
            String lockKey  = jedis.set(skuLockKey, "OK", "NX", "PX", ManageConst.SKULOCK_EXPIRE_PX);
            //set  sku:1001:info   ok    nx  px  10000
            //      k           随意的v           十秒
            if ("OK".equals(lockKey)){
                System.out.println("获取锁!");
                // 从数据库中取得数据
                skuInfo = getSkuInfoDB(skuId);
                // 将是数据放入缓存
                // 将对象转换成字符串
                String skuRedisStr = JSON.toJSONString(skuInfo);
                jedis.setex(skuInfoKey,ManageConst.SKUKEY_TIMEOUT,skuRedisStr);
                //保证每次一个用户用完,都更新到redis
                jedis.close();
                return skuInfo;
            }else {
                System.out.println("等待!");
                // 等待
                Thread.sleep(1000);
                // 自旋
               return getSkuInfo(skuId);
            }
        }else{
            // 有数据
            skuInfo = JSON.parseObject(skuJson, SkuInfo.class);
            jedis.close();
            return skuInfo;
        }
    }catch (Exception e){
        e.printStackTrace();
    }
       // 从数据库返回数据
        return getSkuInfoDB(skuId);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值