多くの人redisson
は、良いか悪いかは言うまでもなく、コメントとして継続をカプセル化することを好みます。ロックの粒度が小さいほど良いと言いたいだけです。
パッケージをプロジェクトに導入する
バージョンの使用3.11.1
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
構成ファイルの追加
spring.redis.cluster.nodes = xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx,xxx.xxx.xxx.xxx
spring.redis.password = passwd
例①
@Autowired
private RedissonClient redissonClient;
public void lockTest(){
RLock lock = redissonClient.getLock(RedisConst.LOCK_PREFIX+"lock:order:xxxxxx");
try {
// 这里要根据实际业务使用isLocked()
if (lock.tryLock(5,30, TimeUnit.SECONDS)) {
//todo 这里实现你的业务逻辑,锁使用原则,粒度越小越好
}
} catch (InterruptedException e) {
System.out.println("获取锁异常");
}finally {
lock.unlock();
}
}
例②楽観的ロックシナリオ
RLock lock = redissonClient.getLock(RedisConst.LOCK_PREFIX + "COMMIT_LOCK");
boolean res=false;
try {
res = lock.tryLock(0, 10, TimeUnit.SECONDS);
System.out.println(res);
if (res){
System.out.println("获取到锁了");
}
if (!res) {
return BusinessResultModel.fail("操作太频繁!");
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
Trylockパラメーターの説明
-
-- waitTime
:最初のパラメーターがロックを取得するまでの最長待機時間。この時間内にロックが取得されたtrue
場合は戻り、この時間以降にロックが取得されなかった場合は戻ります。false
-
-- leastTime
:2番目のパラメータは、ロック取得後のロックの有効期限です。この時間以降にサービスが実行されない場合、ロックは解除されます。 -
-- TimeUnit
:3番目のパラメーターである時間単位。
コードビジネスは複雑であるため、次の状況が発生します。
- 1.同時に3つのスレッドの場合、スレッドは
A、B、C
スレッドAがロックを取得し、B
スレッドがないことができたときにロックを取得することがでてくる。このとき、B
スレッドが実行finally
するメソッドA
リリースロックを。この時点で、スレッドがロックを取得し、ロックを取得し、C
その後、AC
スレッドの実行同時に同じコード。
解決策:実際には、この問題は存在しません。redisson
ロックは、現在ロックを取得しているスレッドによってのみ解放できるため、呼び出しをlock.unlock()
判断する必要がないためです。
- 2.
AB
2つのスレッドが非同時実行で実行されます。スレッドAの実行が完了して戻った後、B
スレッドが入って同じコードを実行するとします。実際、AB
2つのスレッドの要求内容は同じです。これは実際にはべき等の問題です。
このとき、ビジネス上の問題により、データベースにダーティデータが表示されます。たとえば、同じ注文番号に基づいて支払い注文が生成された場合、2つのid
異なる支払い注文が生成されます。
解決策:ビジネスを通じて同じリクエストを判断するには、上記の例を例として取り上げます。条件は同じ注文番号であり、注文が処理されたかどうかを判断します。処理されている場合は、処理の成功に直接戻ります。 。または、処理済みに戻ります。
- 3.
trylock
パラメータによると、ロックの取得結果をすぐに取得したい場合は、最初のパラメータ0
を次のように設定するだけであることがわかります。