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

首先,击穿指的就是 在某件商品参加秒杀这种对一个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);
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis击穿是指一个缓存的key在缓存失效的瞬间,同时有大量的并发请求访问,导致所有的请求都直接访问数据库,造成了数据库短时间内承受大量的请求压力,严重影响网站的性能。 为了解决这个问题,我们可以采用互斥锁的方式来保证只有一个线程可以访问数据库,其他线程都需要等待锁被释放后才能再次尝试获取锁。 下面是使用互斥锁解决Redis击穿问题的示例代码: ```python import redis import threading # 创建 Redis 连接池 redis_pool = redis.ConnectionPool(host='localhost', port=6379, db=0) # 创建 Redis 客户端 redis_client = redis.Redis(connection_pool=redis_pool) # 定义互斥锁 mutex_lock = threading.Lock() def get_data(key): # 先尝试从缓存中获取数据 value = redis_client.get(key) # 如果缓存中存在数据,则直接返回 if value: return value # 否则尝试获取锁 with mutex_lock: # 再次尝试从缓存中获取数据 value = redis_client.get(key) # 如果缓存中存在数据,则直接返回 if value: return value # 如果缓存中不存在数据,则从数据库中获取,并写入缓存 value = db.get(key) redis_client.set(key, value) return value ``` 在上面的代码中,我们首先尝试从缓存中获取数据,如果存在则直接返回。如果缓存中不存在数据,则尝试获取互斥锁,再次尝试从缓存中获取数据。如果获取到锁并且从缓存中还是没有获取到数据,则从数据库中获取数据,并写入缓存。最后,释放锁并返回数据。 需要注意的是,使用互斥锁会影响性能,因此应该尽量避免过多的线程同时访问同一个key。同时,还需要合理设置锁的超时时间,避免死锁的发生。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值