Redis分布式锁解决超卖问题

1、三种分布式锁实现方式对比:

1、数据库分布式锁实现缺点:

1)db操作性能较差,且有锁表的风险;
2)非阻塞操作失败后,需要轮询,占用cpu资源;
3)长时间不commit或者长时间轮询,可能会占用较多连接资源。

2、ZK分布式锁实现缺点:

性能不如redis,因为其写操作(获取锁释放锁)都需要在Leader上执行,然后同步到follower。

3、Redis(缓存)分布式锁实现缺点:

1)过期时间不好控制;
2)非阻塞,操作失败后,需要轮询,占用cpu资源;

2、使用原生redis实现

使用原生Redis的SetNX+Expire实现的分布式锁。

    //方案1 setnx
String lockKey = "zhyRedis";
   //通过val,给锁设置唯一id,防止其他线程删除锁
String clientId = UUID.randomUUID().toString();  //或者雪花生成位置ID
boolean result = redisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 10, TimeUnit.SECONDS); 
  // redisTemplate.expire(lockKey,10,TimeUnit.SECONDS) //旧版本redis(新版直接设置在后面,如上)
  //如果获取不到锁,则返回失败
if(!result){
    result "failed";
}
try {
 //如果能获取到锁,则返回成功
 Integer count = Integer.parseInt(redisTemplate.opsForValue.get("count").toString());
 if (count > 0) {
  Integer realCount = count - 1;
  System.out.Println("购买成功,剩余库存:" + realCount.toString());
  redisTemplate.opsForValue().set("count",realCount.toString());
 }else{
  System.out.Println("购买失败,库存不足");
 }
} catch(Exception e){
 e.printStackTrace();
  return "failed";
} finally{
  //解锁
  //判断当前客户端id与redis分布式中持有的客户端id一致,才能删除锁
 if(clientId.equals(redisTemplate.opsForValue().get(lockKey))){
   redisTemplate.delete(lockKey)
 }
}

3、使用redisson实现

相较于原生Redis的SetNX+Expire实现的分布式锁而言,Redisson的分布式锁组件可以解决原生Redis组合命令带来的一些缺陷,即redis的超时时间值不知道设置为多少才合适。如果此时Redis的服务器节点恰好出现宕机或者服务不能用的情况,那将会导致相应的Key永远存于缓存中,即处于所谓的“永久被锁死”的状态!

底层的实现机制在于:Redisson内部提供了一个监控锁的看门狗WatchDog,其作用在于Redis实例被关闭之前,不断延长锁的有效期。

除此之外,Redisson还通过加锁的方法提供了leaseTime等参数来指定加锁的有效时间,即超过这个时间后“锁”便自动解开了。

//方案2 redisson
String lockKey = "zhyRedis";
RLock rLock = redisson.getLock(lockKey);
try {
 rLock.lock(10, TimeUnit.SECONDS)
 //如果能获取到锁,则返回成功
 Integer count = Integer.parseInt(redisTemplate.opsForValue.get("count").toString());
 if (count > 0) {
  Integer realCount = count - 1;
  System.out.Println("购买成功,剩余库存:" + realCount.toString());
  redisTemplate.opsForValue().set("count",realCount.toString());
 }else{
  System.out.Println("购买失败,库存不足");
 }
} catch(Exception e){
 e.printStackTrace();
 return "failed";
} finally{
 //解锁
 rLock.unlock();
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杭州下小雨~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值