Redis-分布式锁lua脚本+redis原生代码

文章描述了一个基于Redis和Lua脚本实现的分布式锁机制。通过lua脚本确保‘判断’和‘删除’操作的原子性,保证了锁的正确释放。当获取锁时,使用`setIfAbsent`方法设置过期时间防止死锁,解锁时通过lua脚本检查并删除锁,如果解锁失败则进行自旋重试。
摘要由CSDN通过智能技术生成

多个命令的原子性:采用 lua脚本+redis, 由于【判断和删除】是lua脚本执行,所以要么全成功,要么全失败

//获取lock的值和传递的值一样,调用删除操作返回1,否则返回0

String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";

//Arrays.asList(lockKey)是key列表,uuid是参数
Integer result = redisTemplate.execute(new DefaultRedisScript<>(script, Integer.class), Arrays.asList(lockKey), uuid);

全部代码

/**
* 原生分布式锁 开始
* 1、原子加锁 设置过期时间,防止宕机死锁
* 2、原子解锁:需要判断是不是自己的锁
*/
@RestController
@RequestMapping("/api/v1/coupon")
public class CouponController {

  @Autowired
  private StringRedisTemplate redisTemplate;
  
  @GetMapping("add")
  public JsonData saveCoupon(@RequestParam(value = "coupon_id",required = true) int couponId){

      //防止其他线程误删
      String uuid = UUID.randomUUID().toString();

      String lockKey = "lock:coupon:"+couponId;

      lock(couponId,uuid,lockKey);

      return JsonData.buildSuccess();

  }


  private void lock(int couponId,String uuid,String lockKey){


      //lua脚本
      String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";

      Boolean nativeLock = redisTemplate.opsForValue().setIfAbsent(lockKey,uuid,Duration.ofSeconds(30));
      System.out.println(uuid+"加锁状态:"+nativeLock);
      if(nativeLock){
          //加锁成功

          try{
              //TODO 做相关业务逻辑
              TimeUnit.SECONDS.sleep(10L);

          } catch (InterruptedException e) {

          } finally {
              //解锁
              Long result = redisTemplate.execute( new DefaultRedisScript<>(script,Long.class),Arrays.asList(lockKey),uuid);
              System.out.println("解锁状态:"+result);

          }

      }else {
          //自旋操作
          try {
              System.out.println("加锁失败,睡眠5秒 进行自旋");
              TimeUnit.MILLISECONDS.sleep(5000);
          } catch (InterruptedException e) { }

          //睡眠一会再尝试获取锁
          lock(couponId,uuid,lockKey);
      }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值