Redisson 分散ロックの最も基本的な内容

1. はじめに

1.コンセプト

公式サイトアドレス:

https://redisson.org

GitHub アドレス:

https://github.com/redisson/redisson

Redisson は、Redis に基づいて実装された Java インメモリ データ グリッド (In-Memory Data Grid) です。これは、一連の分散型共通 Java オブジェクトを提供するだけでなく、多くの分散型サービスも提供します。

Redisson の目的は、Redis に関するユーザーの関心の分離 (関心の分離) を促進し、ユーザーがビジネス ロジックの処理により集中できるようにすることです。
基本的な分散オブジェクトと高度で抽象的な分散サービスを備えた Redis ベースの分散ツールは、分散車輪の再発明を試みるすべてのプログラマーに、分散の問題のほとんどに対する解決策をもたらします。

Redisson は、Redis に基づいて実装された Java インメモリ データ グリッド (In-Memory Data Grid) です。これは、一連の分散共通 Java オブジェクトを提供するだけでなく、さまざまな分散ロックの実装を含む多くの分散サービスも提供します。

ここに画像の説明を挿入

2. 違い

レディソン、ジェディス、レタスの違いは何ですか? 雷峰と雷峰塔ではありません

Redisson と 2 人の違いは、マウスを使用してグラフィカル インターフェイスを操作するのと、もう 1 つはコマンド ラインを使用してファイルを操作するようなものです。Redisson は高レベルの抽象化であり、Jedis と Lettuce は Redis コマンドのカプセル化です。

Jedis は、Java を介して Redis クライアントに接続するために Redis によって正式に開始されたツールキットです。Redis のさまざまなコマンド サポートを提供します。Lettuce は、拡張可能なスレッドセーフな Redis クライアントです。
通信フレームワークは Netty に基づいており、高度な Redis 機能をサポートします。センチネル、クラスター、パイプライン、自動再接続、Redis データ モデル。Spring Boot 2.x 以降、Lettuce が Jedis に代わって優先 Redis クライアントになりました。
Redisson は Redis に基づいて構築されており、通信は Netty の包括的で新しいミドルウェアに基づいています。エンタープライズ レベルの開発で Redis を使用するための最適なテンプレートである Jedis は、Redis コマンドをカプセル化しています。Lettuce はさらに豊富な API を備えており、サポートもサポートしてい
ますクラスターやその他のモード。しかし、どちらも最後で止まり、Redis データベースを操作するための足場を提供するだけですが、Redisson は Redis、Lua、Netty に基づいた成熟した分散ソリューション、さらには Redis が公式に推奨するツールセットを確立しました。

2. クイックスタート

1、pom.xml

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.13.6</version>
</dependency>

2. Redisson クライアントを構成する

@Configuration
public class RedisConfig {
    
    
    @Bean
    public RedissonClient redissonClient() {
    
    
        // 配置类
        Config config = new Config();
        // 添加redis地址,这里添加了单点的地址,也可以使用config.useClusterServers()添加集群地址 
        config.useSingleServer().setAddress("redis://192.168.150.101:6379").setPassowrd("123321");
        // 创建客户端
        return Redisson.create(config);
    }
}

3. Redisson の分散ロックを使用する

@Resource
private RedissonClient redissonClient;
@Test
void testRedisson() throws InterruptedException {
    
    
    // 获取锁(可重入),指定锁的名称
    RLock lock = redissonClient.getLock("anyLock");
    // 尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位
    boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS);
    // 判断释放获取成功
    if (isLock) {
    
    
        try {
    
    
            System.out.println("执行业务");
        } finally {
    
    
            // 释放锁
            lock.unlock();
        }
    }
}

3. 原則

Lua スクリプトとは何ですか?
Lua スクリプトは、redis に組み込まれた軽量でコンパクトな言語です。その実行は、redis の eval /evalsha コマンドを通じて実行され、操作は Lua スクリプトにカプセル化されます。いずれの場合も、一度に実行されるアトミックな操作です。時間。

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

ロックを取得する Lua スクリプト:

local key = KEYS[1]; -- 锁的key
local threadId = ARGV[1]; -- 线程唯一标识
local releaseTime = ARGV[2]; -- 锁的自动释放时间
-- 判断是否存在
if(redis.call('exists', key) == 0) then
    -- 不存在, 获取锁
    redis.call('hset', key, threadId, '1'); 
    -- 设置有效期
    redis.call('expire', key, releaseTime); 
    return 1; -- 返回结果
end;
-- 锁已经存在,判断threadId是否是自己
if(redis.call('hexists', key, threadId) == 1) then
    -- 不存在, 获取锁,重入次数+1
    redis.call('hincrby', key, threadId, '1'); 
    -- 设置有效期
    redis.call('expire', key, releaseTime); 
    return 1; -- 返回结果
end;
return 0; -- 代码走到这里,说明获取锁的不是自己,获取锁失败

ロックを解除する Lua スクリプト:

local key = KEYS[1]; -- 锁的key
local threadId = ARGV[1]; -- 线程唯一标识
local releaseTime = ARGV[2]; -- 锁的自动释放时间
-- 判断当前锁是否还是被自己持有
if (redis.call('HEXISTS', key, threadId) == 0) then
    return nil; -- 如果已经不是自己,则直接返回
end;
-- 是自己的锁,则重入次数-1
local count = redis.call('HINCRBY', key, threadId, -1);
-- 判断是否重入次数是否已经为0 
if (count > 0) then
    -- 大于0说明不能释放锁,重置有效期然后返回
    redis.call('EXPIRE', key, releaseTime);
    return nil;
else  -- 等于0说明可以释放锁,直接删除
    redis.call('DEL', key);
    return nil;
end;

ここに画像の説明を挿入

Redisson 分散ロック原理:

  • 再入可能: ハッシュ構造を使用してスレッド ID と再入時間を記録します
  • 再試行可能: セマフォと PubSub 関数を使用して、ロックの待機、ウェイクアップ、およびロックの取得失敗に対する再試行メカニズムを実装します。
  • タイムアウトの更新: watchDog を使用して、定期的な間隔 (releaseTime / 3) でタイムアウト期間をリセットします。

4. Redis 分散マスター/スレーブの一貫性

1) 非再入可能 Redis 分散ロック:

  • 原則: setnx の相互排他を使用する; デッドロックを回避するには ex を使用する; ロックを解放するときにスレッド マークを判断する
  • 欠点: 再入不可、再試行不可、ロックタイムアウト失敗

2) 再入可能な Redis 分散ロック:

  • 原則: ハッシュ構造を使用してスレッドのマーキングと再エントリ時間を記録し、watchDog を使用してロック時間を延長し、セマフォを使用してロックの再試行待機を制御します。
  • 欠陥: Redis のダウンタイムによって引き起こされるロックの失敗
    3) Redisson の multiLock:
  • 原則: ロックを正常に取得するには、複数の独立した Redis ノードがすべてのノードで再入可能ロックを取得する必要があります。
  • 欠点: 高い運用コストと保守コスト、複雑な実装

おすすめ

転載: blog.csdn.net/weixin_44624117/article/details/131467229