分散ロック(Redisの実装に基づく)

操作上の注意:githubのredissonを入力した後、次の画像を選択してRedissonプロジェクトの紹介を入力してください(中国語のドキュメント)ここに画像の説明を挿入

1つは、分散ロックの概念です。

分散ロックの目的は次のとおりです。分散環境で、操作(データベースからデータを挿入)を1回だけ実行し、データ操作の繰り返しによって引き起こされる一連の問題を回避するために、setnxコマンドとlua上記の問題を解決するために分散ロックを実装するスクリプト。

setnxコマンドを使用する2つの状況

2.1。ビジネスコードに例外があり、ロック解除(ロックの削除)を実行するコマンドを実行できず、デッドロック(ロックが解除されない)になった場合はどうすればよいですか?

解決策は次のとおりです。try{} finally {}を使用して問題を解決できますが、ビジネスコードが実行され、マシンの電源が突然失われた場合はどうすればよいですか?
最終的な解決策は次のとおりです。ロックの有効期限を設定します。ロックが削除されていなくても、期限切れのロックは自動的に削除されます。
ここに画像の説明を挿入

2.2。ロックの設定と有効期限の設定の間の点滅(ダウンタイム)は依然としてデッドロックになります。それを解決するにはどうすればよいですか?

解決策は次のとおりです。Redisのsetnxexコマンドを使用します。これは、ロックの設定と有効期限の設定を組み合わせたものであり、アトミック操作でもあります。

ここに画像の説明を挿入

2.3。ロックを削除すると、ビジネスコードのタイムアウトにより、ロックが早期に期限切れになり、他の誰かのロックが削除されます。どうすればよいですか?
2.4。ビジネスがタイムアウトした場合、他のスレッドもロックを取得してビジネスオペレーションに入り、ビジネスオペレーションが繰り返されます

上記の問題を解決します。ロックを使用する場合は値をuuidに設定し、削除する場合は比較します。

ここに画像の説明を挿入

2.5。uuidの値が比較され(Redisから値を取得するため)、値が削除されるため、アトミック操作ではありません。uuid値を取得する場合、時間がかかり、最終的に別のスレッドのロック。どうすればよいですか?

解決策:uuid値の比較+比較が成功した後の値の削除=アトミック操作、公式のRedisドキュメントからわかるように、luaスクリプトを使用できます

ここに画像の説明を挿入
ここに画像の説明を挿入

2.6。最終的な形式は次のとおりです。ロックおよびロック解除するときは、原子性を確認してください

ここに画像の説明を挿入
最終コード:

 @Test
    public void testRedisHadoop(){
    
    
        String uuid = UUID.randomUUID().toString();
//        占锁(设置值),并且设置过期时间。这是一个Redis的原子命令
//        NX和EX
        Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 300, TimeUnit.SECONDS);

        if(lock){
    
    
//            加锁成功,执行业务
            try{
    
    
                System.out.println("业务执行。。。。");
            }finally {
    
    
                //            获取值对比+对比成功处理=原子操作------lua脚本
//            通过uuid来删除锁,以防删除别人的锁或者
//            String lockValue = (String) redisTemplate.opsForValue().get("lock");
//            if(uuid.equals(lockValue)){
    
    
//                redisTemplate.delete("lock");
//            }

                //lua脚本
                String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                        "then\n" +
                        "    return redis.call(\"del\",KEYS[1])\n" +
                        "else\n" +
                        "    return 0\n" +
                        "end";

                //删除锁
                Object lock1 = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid);

            }




        }else {
    
    
            System.out.println("获取锁失败,继续尝试");
            testRedisHadoop();//自旋锁
        }


    }

3、Redissonの分散ロック--------リエントラントロック

メソッドbがメソッドaで呼び出された場合、aは1とマークされたロックを追加し、bは1とマークされたロックも追加します。
**リエントラントロックの場合、メソッドが実行されると、内部のbメソッドは、aがロックを解放するのを待つ必要がなく、メソッドのロックを直接使用します。
もしそうであれば
非リエントラントロック、**メソッドが実行されたときに1錠を服用する前に1つのロックを解除するために、その後、ニーズ内部B法は待つし、それを実行します。

3.1。リエントラントロックの2つのロックおよびリロード方法(下の図を参照)

ここに画像の説明を挿入

4、redisの読み取り/書き込みロック

役割は次のとおりです。最新のデータを取得する

書き込みロックは排他ロック(相互排他ロック、排他ロック)であり、読み取りロックは共有ロックです。

書き込みロックが動作しているとき、読み取りロックは待機することしかできません。動作中の書き込みロックがない場合、ロックなしと同じように、読み取りロックが共有されます。

ここに画像の説明を挿入

4.2。読み取り/書き込みロックの補足説明

読み取り+書き込み:読み取りロックがあり、書き込みは待機する必要があります。=======読み取りロックが進行中の場合、書き込みロックは、読み取りロックが解放される(実行が完了する)のを待ってから実行する必要があります。
読み取り+読み取り:ロック解除状態に相当します。現在のすべての読み取りロックは、同時に正常にロックされます。
書き込み+読み取り:読み取りロックを実行し、書き込みロックが解放されるのを待ちます。
書き込み+書き込み:ブロックモード(まで取得する必要があります)。
概要:書き込みロックがある限り、待機する必要があります。

5、redisのブロック

ここに画像の説明を挿入

6、redisセマフォ(セマフォ)

6.1。使用の基本原則:

ここに画像の説明を挿入

6.2。電流制限に使用できます。具体的な原理は次のとおりです。

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/weixin_43983411/article/details/110679363