Redissonツールクラスライブラリ
Redis開発に基づくツールクラスライブラリをお勧めします。このクラスライブラリは、電流制限、ブルームフィルター、分散ロックなど、多くの実用的な機能を提供します。
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.8</version>
</dependency>
今日は分散ロックの実装のみを分析します。Redissonは、非ブロッキングロック、ブロッキングロック、フェアロックなど、ロックするための多くの方法を提供します。
さらに、自動遅延機能が提供されています。タスクが完了していない場合、RedissonはWatchDogを介してロック期間を延長し続けます。
取得ロックのブロック
// 阻塞式获取锁,并且是重入锁
RLock lock = client.getLock("testLock");
try {
lock.lock();
lock.lock();
// 执行业务逻辑
} finally {
lock.unlock();
lock.unlock();
}
ノンブロッキングロック取得
RLock lock = client.getLock("lock");
if (lock.tryLock()) {
System.out.println("获锁成功");
} else {
System.out.println("获锁失败");
}
Redissonはどのように再入可能ロックを実装しますか?
実行スクリプトをロックする
スクリプト入力
パラメータ | 意味 |
---|---|
キー[1] | ロック名 |
ARGV [1] | ロックタイムアウト(ミリ秒) |
ARGV [2] | クライアントの一意のID:スレッドID |
// 锁不存在
if (redis.call('exists', KEYS[1]) == 0) then
// 新建锁,加锁次数设为1,并设置超时时间
redis.call('hincrby', KEYS[1], ARGV[2], 1);
redis.call('pexpire', KEYS[1], ARGV[1]);
return nil;
end;
if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then
// 当前线程已经获取到锁了,将加锁次数加1
redis.call('hincrby', KEYS[1], ARGV[2], 1);
redis.call('pexpire', KEYS[1], ARGV[1]);
return nil;
end;
// 加锁失败
return redis.call('pttl', KEYS[1]);
ロックが成功した場合はnilを返し、そうでない場合はロックの残り時間を返します
実行スクリプトのロックを解除する
スクリプト入力
パラメータ | 意味 |
---|---|
キー[1] | ロック名 |
キー[2 | メッセージのチャネル、チャネル名、redisson_lock__channel:{lockname}のロックを解除します |
ARGV [1] | 0に固定、Redissonはロック解除メッセージを0に固定するように定義します |
ARGV [2] | ロックタイムアウト |
ARGV [3] | クライアントの一意のID:スレッドID |
// 为0表示锁不存在
if (redis.call('hexists', KEYS[1], ARGV[3]) == 0) then
return nil;
end;
// 将加锁次数减1
local counter = redis.call('hincrby', KEYS[1], ARGV[3], -1);
if (counter > 0) then
// 当前线程持有锁,设置超时时间
redis.call('pexpire', KEYS[1], ARGV[2]);
return 0;
else
// 加锁次数为0了,直接删除锁,并广播释放锁的消息
redis.call('del', KEYS[1]);
redis.call('publish', KEYS[2], ARGV[1]);
return 1;
end;
return nil;
ロック解除が成功したときにメッセージを公開するのはなぜですか?
ブロックによってロックを取得するスレッドは、常にロックを取得しようとしないため、ブロックされます。ロック解除メッセージを受信すると、スリープ解除され、再びロックを取得し始めます。
Redissonはどのようにロックの自動遅延を実装しますか?
ロックが正しく解放されないようにするには、通常、ロックのタイムアウトを設定する必要がありますが、これにより新しい問題が発生します。
ロックタイムアウトが10秒に設定されているが、タスクが10秒以内に実行されない場合、ロックは解放され、他のスレッドはロックの取得で問題が発生します。
この問題を解決するために、Redissonは、番犬の自動遅延、つまりロックが成功したときのメカニズムを提供します。バックグラウンドスレッドを開き、成功したロックのthreadIdを渡すと、バックグラウンドスレッドは10秒ごとにチェックして、現在ロックを保持しているスレッドがthreadIdであるかどうかを確認します。
ロック時に指定したタイムアウト時間を表示できないことに注意してください。表示しないと、ウォッチドッグが有効になりません。
ロック時に指定されたロックのタイムアウト時間が表示されない場合、ロックのタイムアウト時間はConfigクラスのlockWatchdogTimeoutプロパティです。このプロパティのデフォルト値は30s(構成可能)であり、自動ウォッチドッグチェックの時間は常にです。ロックのタイムアウト時間に等しい1/3
リファレンスブログ
[1] https://www.cnblogs.com/huangwentian/p/14622441.html?share_token=901429ee-a792-4f2a-87f9-20c47b7cc91c