Redis分散ロック-tryLock
5919 ワード
まとめは前に書きます.
tryLock無パラメータメソッドを使用すると、redissonは自動的にタイミングタスクを追加し、ロックの失効時間をタイミングでリフレッシュし、unlockで失敗すると、ロックが解放されない場合があります.
tryLockがリリース時間を送信すると、このタイミングタスクは追加されません.
テストは次のとおりです.
ロック解除されていません
ロック解除されていません
2、tryLockリリース時間
出力:
ロックは正常に取得されませんでした
テスト済み
redisコンソール:
test01:0>ttl lbhTestLock
"29"test01:0>ttl lbhTestLock
"28"test01:0>ttl lbhTestLock
"27"test01:0>ttl lbhTestLock
"25"test01:0>ttl lbhTestLock
"24"test01:0>ttl lbhTestLock
"22"test01:0>ttl lbhTestLock
"21"
//失効時間がtest 01:0>ttl lbhTestLockにリセットされました
"28"
//プログラムクローズ後test 01:0>ttl lbhTestLock
"18"test01:0>ttl lbhTestLock
"15"test01:0>ttl lbhTestLock
"13"
tryLock()を呼び出してunlockまたはunlockがない場合に失敗し、プログラムが閉じない場合、redissonがロックの有効期限をリフレッシュするため、他のスレッドはこのロックを取得しません.ttlはredissonインスタンスが閉じない限り、redissonによって自動的に消去されます.
ソース分析:
tryLock()を呼び出してメソッドがない場合:
タイム・タスクの有効期限の1/3(デフォルト30 sの1/310 s)ごとにロックの有効期限をリフレッシュする追加
//luaスクリプト解析
まず、このロックキーのmap構造に対応するキー8 a 9649 f 5-f 5 b 5-48 b 4-beaa-d 0 c 24855 f 9 ab:anyLock:1が存在するかどうかを判断し、存在する場合はpexpireコマンドを直接呼び出してロックキーの有効期限を設定し、デフォルトは30000ミリ秒である.
この原理については、以下を参照してください.https://blog.csdn.net/ice24for/article/details/86177152
RLock rLock = redissonClient.getLock("lbhTestLock");
tryLock無パラメータメソッドを使用すると、redissonは自動的にタイミングタスクを追加し、ロックの失効時間をタイミングでリフレッシュし、unlockで失敗すると、ロックが解放されない場合があります.
tryLockがリリース時間を送信すると、このタイミングタスクは追加されません.
テストは次のとおりです.
1、tryLock
@Test
public void testLock() throws Exception {
RLock rLock = redissonClient.getLock("lbhTestLock");
rLock.tryLock();
new Thread(new Runnable() {
@Override
public void run() {
try {
if (rLock.tryLock()) {
System.out.println(" ");
} else {
System.out.println(" ");
}
Thread.sleep(35000);
if (rLock.tryLock()) {
System.out.println(" ");
} else {
System.out.println(" ");
}
} catch (Exception e) {
}
}
}).start();
Thread.sleep(40000);
rLock.unlock();
}
:
ロック解除されていません
ロック解除されていません
2、tryLockリリース時間
rLock.tryLock(0,30,TimeUnit.SECONDS);
出力:
ロックは正常に取得されませんでした
テスト済み
@Test
public void testLock2() throws Exception {
new Thread(new Runnable() {
@Override
public void run() {
RLock rLock = redissonClient.getLock("lbhTestLock");
rLock.tryLock();
}
}).start();
Thread.sleep(600000);
//rLock.unlock();
}
redisコンソール:
test01:0>ttl lbhTestLock
"29"test01:0>ttl lbhTestLock
"28"test01:0>ttl lbhTestLock
"27"test01:0>ttl lbhTestLock
"25"test01:0>ttl lbhTestLock
"24"test01:0>ttl lbhTestLock
"22"test01:0>ttl lbhTestLock
"21"
//失効時間がtest 01:0>ttl lbhTestLockにリセットされました
"28"
//プログラムクローズ後test 01:0>ttl lbhTestLock
"18"test01:0>ttl lbhTestLock
"15"test01:0>ttl lbhTestLock
"13"
tryLock()を呼び出してunlockまたはunlockがない場合に失敗し、プログラムが閉じない場合、redissonがロックの有効期限をリフレッシュするため、他のスレッドはこのロックを取得しません.ttlはredissonインスタンスが閉じない限り、redissonによって自動的に消去されます.
ソース分析:
tryLock()を呼び出してメソッドがない場合:
@Override
public boolean tryLock() {
return get(tryLockAsync());
}
@Override
public RFuture tryLockAsync() {
return tryLockAsync(Thread.currentThread().getId());
}
public RFuture tryLockAsync(long threadId) {
return tryAcquireOnceAsync(-1, null, threadId);
}
private RFuture tryAcquireOnceAsync(long leaseTime, TimeUnit unit, final long threadId) {
//
if (leaseTime != -1) {
return tryLockInnerAsync(leaseTime, unit, threadId, RedisCommands.EVAL_NULL_BOOLEAN);
}
//
RFuture ttlRemainingFuture = tryLockInnerAsync(LOCK_EXPIRATION_INTERVAL_SECONDS, TimeUnit.SECONDS, threadId, RedisCommands.EVAL_NULL_BOOLEAN);
// Listener !
ttlRemainingFuture.addListener(new FutureListener() {
@Override
public void operationComplete(Future future) throws Exception {
if (!future.isSuccess()) {
return;
}
Boolean ttlRemaining = future.getNow();
// lock acquired
// tryLock , tryLock
if (ttlRemaining) {
//
scheduleExpirationRenewal(threadId);
}
}
});
return ttlRemainingFuture;
}
private void scheduleExpirationRenewal(final long threadId) {
if (expirationRenewalMap.containsKey(getEntryName())) {
return;
}
Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {
@Override
public void run(Timeout timeout) throws Exception {
//
RFuture future = commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +
// key { }
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return 1; " +
"end; " +
"return 0;",
Collections.
タイム・タスクの有効期限の1/3(デフォルト30 sの1/310 s)ごとにロックの有効期限をリフレッシュする追加
//luaスクリプト解析
まず、このロックキーのmap構造に対応するキー8 a 9649 f 5-f 5 b 5-48 b 4-beaa-d 0 c 24855 f 9 ab:anyLock:1が存在するかどうかを判断し、存在する場合はpexpireコマンドを直接呼び出してロックキーの有効期限を設定し、デフォルトは30000ミリ秒である.
この原理については、以下を参照してください.https://blog.csdn.net/ice24for/article/details/86177152