ホームページ データベース Redis Redis分散ロックの実装方法

Redis分散ロックの実装方法

May 10, 2023 pm 09:01 PM
redis 分散ロック 実装

Redis は、データの保存と読み取りができるオープンソースのメモリ内データ キャッシュ システムです。分散環境では、複数のアプリケーションが同じリソース上で同時に動作すると、ダーティ データやデータの不整合に関する問題が発生する可能性があります。この問題を解決するには、分散ロックを導入してデータの一貫性を確保します。

この記事は、Redis 分散ロックのアプリケーション シナリオ、原則、​​実装方法を紹介することで、読者が Redis を使用して分散ロックを実装する方法を理解するのに役立ちます。

1. アプリケーション シナリオ

分散システムでは、アプリケーションは複数のリソースを同時に操作する必要がある場合があります。では、このアプリケーションのリソース操作がスレッドセーフであることを確認するにはどうすればよいでしょうか?現時点では、分散ロックを導入する必要があります。

分散ロックを使用すると、次の問題を解決できます。

(1) 複数のクライアントが同じリソースを同時に変更して、データの不整合が生じることを回避します。

(2) ネットワーク遅延やその他の問題により、クライアントが同じリソースに複数の変更を加えることを防ぎます。

(3) クライアントがリソースを長時間占有して、他のクライアントがリソースに正常にアクセスできなくなることを防止します。

2. 原則

Redis 分散ロックは主に setnx コマンドを通じて実装されます。 setnx コマンドは Redis のアトミック操作であり、複数のクライアントの同時操作において、1 つのクライアントだけがキーと値のペアを Redis に正常に設定できるようにします。

次に、Redis 分散ロックの具体的な実装を見てみましょう。

3. 実装方法

(1) ロックの取得

ロックの取得処理では、setnx コマンドを使用してキーと値のペアを設定する必要があります。 。設定が成功すればロックを取得できたことになりますが、設定に失敗した場合は一定時間待ってから再度ロックの取得を試みる必要があります。

まず、次のコード ブロックを通じてロックを取得します。

boolean lock = jedis.setnx(key, value) == 1;
ログイン後にコピー

このうち、key と value はそれぞれロックの名前と値を表し、jedis は Redis クライアントを表します。

ロックの名前が Redis に存在しない場合、上記のコードの戻り値は 1 で、設定が成功し、ロックが取得されたことを示します。ロック名がすでに Redis に存在する場合、上記のコードの戻り値は 0 となり、設定が失敗し、ロックの取得が失敗したことを示します。

(2) ロックを解放する

ロックを解放するプロセスでは、del コマンドを使用して Redis のキーと値のペアを削除する必要があります。

まず、次のコード ブロックを通じてロックを解放します。

long result = jedis.del(key);
ログイン後にコピー

このうち、key はロックの名前を表し、jedis は Redis クライアントを表します。

Redis のキーと値のペアが正常に削除された場合、上記のコードの戻り値は 1 で、ロックが正常に解放されたことを示します。キーと値のペアが Redis に存在しない場合、上記のコードの戻り値は 0 で、ロックの解放が失敗したことを示します。

(3) ロックの有効期限を設定する

ロックが常に占有されることを防ぐために、ロックの有効期限を設定する必要があります。ロック所有者が一定期間内にロックを解放しない場合、Redis はロックが永久に占有されるのを防ぐために自動的にロックを削除します。

まず、次のコード ブロックを通じてロックの有効期限を設定する必要があります:

jedis.expire(key, timeout);
ログイン後にコピー

このうち、key はロックの名前を表し、timeout はロックの有効期限を表します。数秒でロックします。

他のクライアントのロックを誤って削除しないようにするには、ロックの値が、ロックを取得したときに設定した値と一致しているかどうかを確認する必要があります。

String value = jedis.get(key);
if (StringUtils.isNotBlank(value) && value.equals(uuid)) {
  jedis.del(key);
}
ログイン後にコピー

このうち、uuid はロックを取得するクライアントの一意の ID を表します。

(4) 他のクライアントのロックを誤って削除しないようにする

ロックを使用した後は、正しくロックを解除する必要があります。そうしないと、他のクライアントのロックが誤って削除されてしまいます。

したがって、他のクライアントのロックが誤って削除されるのを防ぐために、コードに一意の識別子を追加する必要があります。

まず、ロックを取得するプロセスで、以下に示すように、クライアントの一意の識別子を生成する必要があります。

String uuid = UUID.randomUUID().toString();
ログイン後にコピー

次に、ロックを取得して解放するプロセスで、ロックの場合、現在のクライアントがロックを取得したかどうかを判断するには、キーに対応する値が uuid と等しいかどうかを判断する必要があります。ロックの取得とロックの解放のプロセスでは、uuid を次のように設定する必要があります。 value をキーに対応する値に置き換えます。

具体的なコードは次のとおりです。

boolean lock = jedis.setnx(key, uuid) == 1;
if (lock) {
  jedis.expire(key, timeout);
}

// 释放锁
String value = jedis.get(key);
if (StringUtils.isNotBlank(value) && value.equals(uuid)) {
  jedis.del(key);
}
ログイン後にコピー

(5) 間違った使用例

分散ロックを使用する過程で、次のような状況が発生した場合、 Deadlock:

// 获取锁
jedis.setnx(key, value);

// 不释放锁
ログイン後にコピー

したがって、ロックを使用するときは、ロックを正しく解放することに注意する必要があります。そうしないと、システムに予期しない結果が生じます。

(6) 実装クラス

最後に、上記のコードを Redis 分散ロック クラスにカプセル化する方法を見てみましょう。

import redis.clients.jedis.Jedis;

import java.util.UUID;

public class RedisLock {

    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";

    private Jedis jedis;

    public RedisLock(Jedis jedis) {
        this.jedis = jedis;
    }

    /**
     * 尝试获取分布式锁
     * @param key 锁
     * @param requestId 请求标识
     * @param expireTime 超期时间(秒)
     * @return 是否获取成功
     */
    public boolean tryGetDistributedLock(String key, String requestId, int expireTime) {
        String result = jedis.set(key, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
        return LOCK_SUCCESS.equals(result);
    }

    /**
     * 释放分布式锁
     * @param key 锁
     * @param requestId 请求标识
     * @return 是否释放成功
     */
    public boolean releaseDistributedLock(String key, String requestId) {
        String value = jedis.get(key);
        if (value != null && value.equals(requestId)) {
            jedis.del(key);
            return true;
        }
        return false;
    }

    /**
     * 获取请求标识
     * @return 请求标识
     */
    public static String getRequestId() {
        return UUID.randomUUID().toString();
    }

}
ログイン後にコピー

この時点で、Redis 分散ロックの実装が完了しました。

4. 概要

この記事は、Redis 分散ロックのアプリケーション シナリオ、原則、​​実装方法を紹介することで、読者が Redis を使用して分散ロックを実装する方法を理解するのに役立ちます。分散ロックの実装は比較的複雑であるため、ロックの値が取得時に設定された値と一致するかどうかを判断したり、取得のプロセス中にキーの値として uuid を設定したりするなど、いくつかの詳細に注意を払う必要があります。対応する値は中です。分散ロックを正しく使用することによってのみ、分散システム内のデータの一貫性と信頼性を確保できます。

以上がRedis分散ロックの実装方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Redisクラスターモードの構築方法 Redisクラスターモードの構築方法 Apr 10, 2025 pm 10:15 PM

Redisクラスターモードは、シャードを介してRedisインスタンスを複数のサーバーに展開し、スケーラビリティと可用性を向上させます。構造の手順は次のとおりです。異なるポートで奇妙なRedisインスタンスを作成します。 3つのセンチネルインスタンスを作成し、Redisインスタンスを監視し、フェールオーバーを監視します。 Sentinel構成ファイルを構成し、Redisインスタンス情報とフェールオーバー設定の監視を追加します。 Redisインスタンス構成ファイルを構成し、クラスターモードを有効にし、クラスター情報ファイルパスを指定します。各Redisインスタンスの情報を含むnodes.confファイルを作成します。クラスターを起動し、CREATEコマンドを実行してクラスターを作成し、レプリカの数を指定します。クラスターにログインしてクラスター情報コマンドを実行して、クラスターステータスを確認します。作る

Redisデータをクリアする方法 Redisデータをクリアする方法 Apr 10, 2025 pm 10:06 PM

Redisデータをクリアする方法:Flushallコマンドを使用して、すべての重要な値をクリアします。 FlushDBコマンドを使用して、現在選択されているデータベースのキー値をクリアします。 [選択]を使用してデータベースを切り替え、FlushDBを使用して複数のデータベースをクリアします。 DELコマンドを使用して、特定のキーを削除します。 Redis-CLIツールを使用してデータをクリアします。

Redisコマンドの使用方法 Redisコマンドの使用方法 Apr 10, 2025 pm 08:45 PM

Redis指令を使用するには、次の手順が必要です。Redisクライアントを開きます。コマンド(動詞キー値)を入力します。必要なパラメーターを提供します(指示ごとに異なります)。 Enterを押してコマンドを実行します。 Redisは、操作の結果を示す応答を返します(通常はOKまたは-ERR)。

Redisロックの使用方法 Redisロックの使用方法 Apr 10, 2025 pm 08:39 PM

Redisを使用して操作をロックするには、setnxコマンドを介してロックを取得し、有効期限を設定するために有効期限コマンドを使用する必要があります。特定の手順は次のとおりです。(1)SETNXコマンドを使用して、キー価値ペアを設定しようとします。 (2)expireコマンドを使用して、ロックの有効期限を設定します。 (3)Delコマンドを使用して、ロックが不要になったときにロックを削除します。

Redisキューの読み方 Redisキューの読み方 Apr 10, 2025 pm 10:12 PM

Redisのキューを読むには、キュー名を取得し、LPOPコマンドを使用して要素を読み、空のキューを処理する必要があります。特定の手順は次のとおりです。キュー名を取得します:「キュー:キュー」などの「キュー:」のプレフィックスで名前を付けます。 LPOPコマンドを使用します。キューのヘッドから要素を排出し、LPOP Queue:My-Queueなどの値を返します。空のキューの処理:キューが空の場合、LPOPはnilを返し、要素を読む前にキューが存在するかどうかを確認できます。

Redisのソースコードを読み取る方法 Redisのソースコードを読み取る方法 Apr 10, 2025 pm 08:27 PM

Redisソースコードを理解する最良の方法は、段階的に進むことです。Redisの基本に精通してください。開始点として特定のモジュールまたは機能を選択します。モジュールまたは機能のエントリポイントから始めて、行ごとにコードを表示します。関数コールチェーンを介してコードを表示します。 Redisが使用する基礎となるデータ構造に精通してください。 Redisが使用するアルゴリズムを特定します。

基礎となるRedisを実装する方法 基礎となるRedisを実装する方法 Apr 10, 2025 pm 07:21 PM

Redisはハッシュテーブルを使用してデータを保存し、文字列、リスト、ハッシュテーブル、コレクション、注文コレクションなどのデータ構造をサポートします。 Redisは、スナップショット(RDB)を介してデータを維持し、書き込み専用(AOF)メカニズムを追加します。 Redisは、マスタースレーブレプリケーションを使用して、データの可用性を向上させます。 Redisは、シングルスレッドイベントループを使用して接続とコマンドを処理して、データの原子性と一貫性を確保します。 Redisは、キーの有効期限を設定し、怠zyな削除メカニズムを使用して有効期限キーを削除します。

Redis用のメッセージミドルウェアの作成方法 Redis用のメッセージミドルウェアの作成方法 Apr 10, 2025 pm 07:51 PM

Redisは、メッセージミドルウェアとして、生産消費モデルをサポートし、メッセージを持続し、信頼できる配信を確保できます。メッセージミドルウェアとしてRedisを使用すると、低遅延、信頼性の高いスケーラブルなメッセージングが可能になります。

See all articles