Redis分布式锁实现

redis一个命令setnx
SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写
将 key 的值设为 value ,当且仅当 key 不存在.
返回值:
设置成功,返回 1 。
设置失败,返回 0 。
如下思路是设置一个过期锁。但是实际开发中这个过期时间很难判断,需要加守护线程进行重新设置过期时间。
public boolean tryLock(String key, String requestId, int expireTime) {
//使用jedis的api,保证原子性
//NX 不存在则操作 EX 设置有效期,单位是秒
String result = jedis.set(key, requestId, "NX", "EX", expireTime);
//返回OK则表示加锁成功
return "OK".equals(result);
}
有一种方法比较靠谱一点,就是给锁续期。在Redisson框架实现分布式锁的思路,就使用watchDog机制实现锁的续期。当加锁成功后,同时开启守护线程,默认有效期是30秒,每隔10秒就会给锁续期到30秒,只要持有锁的客户端没有宕机,就能保证一直持有锁,直到业务代码执行完毕由客户端自己解锁,如果宕机了自然就在有效期失效后自动解锁。

秒杀场景,幂等返回
使用自旋操作:

long timeout = 5000; // 5秒超时秒杀失败
try {
  Long start = System.currentTimeMillis();
  while(true) {
     String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
     if ("OK".equals(result)) {
        // 秒杀逻辑
        return true;
     }
     
     long time = System.currentTimeMillis() - start;
      if (time>=timeout) {
          return false;
      }
      try {
          Thread.sleep(50);
      } catch (InterruptedException e) {
          e.printStackTrace();
      }
  }
} finally{
    unlock(lockKey,requestId);
}  
return false;

posted @ 2021-04-26 17:30  倔强的老铁  阅读(57)  评论(0编辑  收藏  举报