スプリングブーツのRedisに基づく分散ロックLUAスクリプトを実装【それがされている]のRedisにおける単一点に基づいて
ブート1.5.xのは、Redisのに基づく分散ロックのluaスクリプトを達成.Spring
1.pom.xml
<! - Redisの- > < 依存> < groupIdを> org.springframework.boot </ groupIdを> < たartifactId >春・ブート・スターター・データのRedis </ たartifactId > </ 依存関係>
2.RedisLockツール(春インジェクション)
インポートorg.springframework.beans.factory.annotation.Autowired; インポートorg.springframework.data.redis.core.RedisTemplate; インポートorg.springframework.data.redis.core.script.DefaultRedisScript; インポートorg.springframework.data.redis。 core.script.RedisScript; インポートorg.springframework.data.redis.serializer.StringRedisSerializer; インポートorg.springframework.stereotype.Component; インポートjava.util.Collections; / ** *春ブート1.5.xの *のluaスクリプトのRedisの使用分散ロックのシングルポイントの実装に基づいて * * Luaのスクリプトアトミックオペレーションとして、及びアトミック操作をロック設定・タイムアウトを確実にするために * @author SXD @date 2019年5月27日10時52は、* / * @Component パブリック クラスRedisLock { @Autowired RedisTemplate redisTemplate; プライベート 静的 最終長い1L = SUCCESS ; / ** *ゲットロック * * @param キーのlockKey Redisの * @paramの値は、他の要求の解除を防止すること、ランダムな文字列値のRedisのを必要としますロック * @paramの他の要求が発生し、デッドロックを防ぐためにexpireTimeのRedisのキーの有効期限は、通常の操作を実行することはできません * @return * / パブリック ブールロック(lockKey文字列、文字列の値が、int型expireTimeを){ 文字列スクリプト= "もしredis.call( 'setNx'、KEYS [1]、ARGV [1])を" + "であればredis.call( 'get'が、KEYS [1])== ARGV [1]次に、" + 」リターンredis.call( '期限切れ'、KEYS [1]、ARGV [2]) "+ "他の"+ "リターン0 "+ "終了"+ "終了" ; RedisScript <文字列> redisScript = 新しい DefaultRedisScript <>(スクリプト、文字列。クラス); // 对非文字列类型的序列化 redisTemplate.setKeySerializer(新StringRedisSerializer()); redisTemplate。 redisTemplate.execute(redisScript、Collections.singletonList(lockKey)、値、String.valueOf(expireTime)); を返すSUCCESS.equals(結果を); } / ** *ロック解除 * * @param キーのlockKey Redisの * @ PARAMの値Redisの、同じ比の値の値、プラス正常に存在するロック解除することを決定するために要求 * @return * / パブリック ブールUNLOCK(lockKey文字、文字列値){ 文字列スクリプト =「redis.call IF( 『GET』 [1]、KEYS)== ARGVのredis.call次いでリターン( 'デル'、KEYS)他戻り0 "エンド[1] [1] ; redisScript <ストリング> = redisScript新しい DefaultRedisScript <>(スクリプト、文字列。クラス); 試す{ オブジェクト結果 = redisTemplate.execute(redisScript、Collections.singletonList(lockKey)、値)。 もし(SUCCESS.equals(結果)){ 戻り 真。 } } キャッチ(例外e){ e.printStackTrace(); } を返す 偽。 } }
3.controllerの使用
/ ** *分散ロック・ロジックを使用して 値expireTimeキー準備1. * *値はランダムな文字列を必要とする * expireTimeロックの有効期限は、ビジネス上の意思決定の指標に基づいています * * 2.ロック取得 *成功した買収、業務執行の実現を完全に、ロックを解除し 、*取得に失敗したことを、取得を再試行し、買収が成功するまでロックを取得するための時間間隔に注意を払う、事業の実施、そして最終的にロックを解除 * *注: *ビジネスをロックのRedisのために、短い時間のかかる業務で使用するようにしてください上。 * * / @RequestMapping( "/テスト" ) 公共 ボイド試験(){ ブールフラグに= falseに ; // ロックを取得するための識別子が正常である 文字列UUID = UUID.randomUUID()のtoString();. // Redisの値が文字列であります乱数 フラグに= Lock.lock(「mykey1」、UUID ,. 5 ); IF (フラグに){ ビジネス(UUID); } 他{ // ロックは通常の取得により、リトライを取得されていない場合は成功したロックされるまで しばらく(!{旗で) 試してみます{ // のRedisとの相互作用の数を減らすために再試行間隔 のThread.sleep(3000 ); のSystem.out.printlnは( "リトライ" ); フラグに = Lock.lock( "mykey1"、UUID ,. 5 ); IF (フラグに) { ビジネス(UUID); } 他{ 続行; } } キャッチ(InterruptedExceptionあるE){ e.printStackTrace(); } } } } 公共 ボイドビジネス(UUID文字列){ 試み{ System.out.printlnは( "ビジネスの成功の実装をロック" ); のThread.sleep( 10000 ); } キャッチ(InterruptedExceptionあるE){ e.printStackTrace(); } 最後に{ // サービスの実行が正常にロック解除する完成され lock.unlock( "mykey1を"、UUID)。 } }
Redisのに基づいて、分散ロック・LUAスクリプトの二つの.springブート2.xの実装
1。