1. Redisson 分布式锁
可重入:利用hash结构记录线程id和重入次数
可重试:利用信号量和PubSub功能实现等待、唤醒,获取锁失败的重试机制
超时续约:利用watchDog,开启一个定时任务,每隔一段时间(releaseTime / 3),重置超时时间
主从一致性问题:利用MultiLock锁,Redis不再区分主从节点,只有所有的节点都写入成功,才是加锁成功,假设现在某个节点挂了,那么他去获取锁的时候,只要有一个节点拿不到,都不能算是加锁成功,就保证了加锁的可靠性
MultiLock原理
构造函数
1 2 3 4 5 6 7 8 9 10 11 12
| RLock lock1 = redissonClient.getLock("lock"); RLock lock2 = redissonClient2.getLock("lock"); RLock lock3 = redissonClient3.getLock("lock"); lock = redissonClient.getMultiLock(lock1, lock2, lock3);
public RedissonMultiLock(RLock... locks) { if (locks.length == 0) { throw new IllegalArgumentException("Lock objects are not defined"); } else { this.locks.addAll(Arrays.asList(locks)); } }
|
联锁的tryLock
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException { long newLeaseTime = -1L; if (leaseTime != -1L) { if (waitTime == -1L) { newLeaseTime = unit.toMillis(leaseTime); } else { newLeaseTime = unit.toMillis(waitTime) * 2L; } } long time = System.currentTimeMillis(); long remainTime = -1L; if (waitTime != -1L) { remainTime = unit.toMillis(waitTime); } long lockWaitTime = this.calcLockWaitTime(remainTime); int failedLocksLimit = this.failedLocksLimit(); List<RLock> acquiredLocks = new ArrayList(this.locks.size()); ListIterator<RLock> iterator = this.locks.listIterator();
while(iterator.hasNext()) { RLock lock = (RLock)iterator.next();
boolean lockAcquired; try { if (waitTime == -1L && leaseTime == -1L) { lockAcquired = lock.tryLock(); } else { long awaitTime = Math.min(lockWaitTime, remainTime); lockAcquired = lock.tryLock(awaitTime, newLeaseTime, TimeUnit.MILLISECONDS); } } catch (RedisResponseTimeoutException var21) { this.unlockInner(Arrays.asList(lock)); lockAcquired = false; } catch (Exception var22) { lockAcquired = false; } if (lockAcquired) { acquiredLocks.add(lock); } else { if (this.locks.size() - acquiredLocks.size() == this.failedLocksLimit()) { break; } if (failedLocksLimit == 0) { this.unlockInner(acquiredLocks); if (waitTime == -1L) { return false; }
failedLocksLimit = this.failedLocksLimit(); acquiredLocks.clear(); while(iterator.hasPrevious()) { iterator.previous(); } } else { --failedLocksLimit; } } if (remainTime != -1L) { remainTime -= System.currentTimeMillis() - time; time = System.currentTimeMillis(); if (remainTime <= 0L) { this.unlockInner(acquiredLocks); return false; } } } if (leaseTime != -1L) { List<RFuture<Boolean>> futures = new ArrayList(acquiredLocks.size()); Iterator var24 = acquiredLocks.iterator();
while(var24.hasNext()) { RLock rLock = (RLock)var24.next(); RFuture<Boolean> future = ((RedissonLock)rLock).expireAsync(unit.toMillis(leaseTime), TimeUnit.MILLISECONDS); futures.add(future); }
var24 = futures.iterator();
while(var24.hasNext()) { RFuture<Boolean> rFuture = (RFuture)var24.next(); rFuture.syncUninterruptibly(); } } return true; }
|