原文链接
分布式锁一般有如下的特点:
- 互斥性: 同一时刻只能有一个线程持有锁
 
- 可重入性: 同一节点上的同一个线程如果获取了锁之后能够再次获取锁
 
- 锁超时:和J.U.C中的锁一样支持锁超时,防止死锁
 
- 高性能和高可用: 加锁和解锁需要高效,同时也需要保证高可用,防止分布式锁失效
 
- 具备阻塞和非阻塞性:能够及时从阻塞状态中被唤醒
 
lua脚本的方式,放在一个事务中去
1 2 3 4 5 6 7 8 9 10 11 12
   | public boolean tryLock_with_lua(String key, String UniqueId, int seconds) {     String lua_scripts = "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then" +             "redis.call('expire',KEYS[1],ARGV[2]) return 1 else return 0 end";     List<String> keys = new ArrayList<>();     List<String> values = new ArrayList<>();     keys.add(key);     values.add(UniqueId);     values.add(String.valueOf(seconds));     Object result = jedis.eval(lua_scripts, keys, values);          return result.equals(1L); }
  | 
 
1 2 3 4 5 6
   | SET key value[EX seconds][PX milliseconds][NX|XX]
  EX seconds: 设定过期时间,单位为秒 PX milliseconds: 设定过期时间,单位为毫秒 NX: 仅当key不存在时设置值 XX: 仅当key存在时设置值
   | 
 
释放锁的情况,需要对value进行验证,仅释放自己设置的锁?
针对redis集群的方式,采用投票的机制来决定是否真正算获得了锁,也就是所谓的redLock算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   |     public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws             InterruptedException {
          int failedLocksLimit = failedLocksLimit();         List<RLock> acquiredLocks = new ArrayList<RLock>(locks.size());
          for (ListIterator<RLock> iterator = locks.listIterator(); iterator.hasNext(); ) {             RLock lock = iterator.next();             boolean lockAcquired;             try {
                  lockAcquired = lock.tryLock(awaitTime, newLeaseTime, TimeUnit.MILLISECONDS);             } catch (RedisConnectionClosedException | RedisResponseTimeoutException e) {
                  unlockInner(Arrays.asList(lock));                 lockAcquired = false;             } catch (Exception e) {
                  lockAcquired = false;             }             if (lockAcquired) {
                  acquiredLocks.add(lock);             } else {
                  if (locks.size() - acquiredLocks.size() == failedLocksLimit()) {                     break;                 }             }         }         return true;     }
   |