SpringBoot 2.3.4 Redissonを統合して分散ロックを実現


概要
分散プロジェクトでは分散ロックがしばしば必要であり、redis関連コマンドSET key value[EX seconds][PX milliseconds][NX][XX]またはコマンドSETNXを直接使用して分散ロックを実現することができる.コマンド方式による分散ロックの実現には、ロック解除前にプログラム異常が発生し、ロック解除ができなくなったり、期限切れが設定されたりしてスレッドAが取得したロックが期限切れでredisによって削除されたり、このときAがDELコマンドを実行するなどの問題があり、これらの問題を解決するためにLuaスクリプトを導入することで、プログラムをより複雑にすることができる.redisは、RedisベースのRedisson分散リダイレクトロックRLock Javaオブジェクトがjava.util.concurrent.locks.Lockインタフェースを実装している公式ドキュメントを参照して、分散ロックをより容易に実現するコンポーネントRedissonを発表しました.使用方法はReentrantLockと同じです.本文は主にSpringBoot 2.3統合Redissonによる分散ロックの簡単な実装を紹介し,テストを容易にするためにswaggerをテストツールとして用いた.
導入依存
SpringBoot統合Redissonコア依存度は次のとおりです.
<dependency>
    <groupId>org.redissongroupId>
    <artifactId>redisson-spring-boot-starterartifactId>
    <version>3.13.5version>
dependency>
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redisartifactId>
dependency>

プロファイル
Redissonには2つの構成方法があり、プログラム化構成とymlファイル構成のプログラム化構成方法はConfigオブジェクトインスタンスを構築することによって実現され、コードは以下の通りである.
@Bean(destroyMethod = "shutdown")
public RedissonClient redisson() throws IOException {
     
    Config config = new Config();
    config.useSingleServer().setAddress("redis://192.168.108.11:6379");
    return Redisson.create(config);
}

Redissonは、クラスタモード、歩哨モード、主従モードなど、さまざまなモードをサポートしています.ここでは、単一ノードモードymlファイルの構成には、アプリケーション.ymlプロファイルでは構成できません.主な構成は次のとおりです.
singleServerConfig:
  idleConnectionTimeout: 10000 #      (  ),  10000
  connectTimeout: 10000 #      (  ),  10000
  timeout: 3000 #      (  ),  3000
  retryAttempts: 3 #        
  retryInterval: 1500 #          (  ),  1500
  password: null
  subscriptionsPerConnection: 5 #          ,  5
  clientName: null #     
  address: "redis://127.0.0.1:6379"
  subscriptionConnectionMinimumIdleSize: 1 #               ,  1
  subscriptionConnectionPoolSize: 50 #          ,  50
  connectionMinimumIdleSize: 24 #       ,  32
  connectionPoolSize: 64 #     ,  64
  database: 0
  dnsMonitoringInterval: 5000 #DNS      (  ),  5000
threads: 16
nettyThreads: 32
codec: ! {
     }
"transportMode": "NIO"

ここで注意しなければならないのは、Redisson中国語網が提供した例はプロジェクトの起動時にエラーを報告し、英語網を使用して提供した例は正常にプロジェクトを起動することができ、中国語網のドキュメントがタイムリーに更新されていないと推定されている.以上の構成はRedisson英語網がymlファイルを使用して構成することから抜粋され、新しい構成クラスを作成して構成ファイルをロードし、RedissonClientをインスタンス化する必要がある.コードは次のとおりです.
@Bean(destroyMethod = "shutdown")
public RedissonClient redisson() throws IOException {
     
    Config config = Config.fromYAML(new ClassPathResource("application-single.yml").getInputStream());
    RedissonClient redisson = Redisson.create(config);
    return redisson;
}

注意:ClassPathResourceでプロファイルをロードする
分散ロックコアコードの実装
public AjaxResult selectUserForLockById(@PathVariable Long id) {
     
    String key = "user_" + id;
    RLock readLock = redissonService.getReadLock(key);
    readLock.lock();//  
    //readLock.lock(10, TimeUnit.SECONDS);          ,     redisson  30 
    SysUser user = new SysUser();
    try {
     
        logger.info("    ,        ...");
        user = userService.getById(id);
    } catch (Exception e) {
     
        e.printStackTrace();
    } finally {
     
        logger.info("   ....");
        readLock.unlock();
    }
    return AjaxResult.ok().data("user", user);
}

しんごうりょうコアコード
public AjaxResult selectUserForSemaphoreById(@PathVariable Long id) {
     
    String key = "user_semaphore_" + id;
    RSemaphore semaphore = redissonService.getSemaphore(key);
    //         
    semaphore.trySetPermits(5);
    SysUser user = new SysUser();
    try {
     
        boolean flag = semaphore.tryAcquire();
        if (flag) {
     
            logger.info("       ,      ......");
            user = userService.getById(id);
            logger.info("      ,     ......");
            semaphore.release();
        } else {
     
            logger.info("       ,      ......");
            user = null;
        }
    } catch (Exception e) {
     
        e.printStackTrace();
    }
    return AjaxResult.ok().data("user", user);
}

Redissonはまた公平なロック、インターロック、赤いロック、閉鎖などの実現を提供して、本文は一つ一つ紹介しないで、もっと詳しい詳細はRedissonの公式サイトを参照してください