目次
RedLock
ホームページ データベース Redis Redis で分散ロックが必要なのはなぜですか?どのように達成するか?

Redis で分散ロックが必要なのはなぜですか?どのように達成するか?

Oct 20, 2021 am 10:37 AM
redis 分散ロック

この記事では、Redis の分散ロック、分散ロックが必要な理由、Redis が分散ロックを実装する方法について紹介します。

Redis で分散ロックが必要なのはなぜですか?どのように達成するか?

#分散ロックが必要な理由

分散ロックが必要な理由

使用分散ロックの目的は、共有リソース上で同時に 1 つのクライアントだけが操作できるようにすることだけにすぎません。

分散アプリケーションで論理処理を実行するときに、同時実行性の問題がよく発生します。 [関連する推奨事項:

Redis ビデオ チュートリアル ]

たとえば、操作にはユーザーのステータスを変更する必要があります。ステータスを変更するには、まずユーザーのステータスを読み取り、メモリ内で変更する必要があります。 、変更後に保存し直します。このような操作を同時に実行すると、状態の読み取りと保存という 2 つの操作がアトミックではないため、同時実行性の問題が発生します。

現時点では、プログラムの同時実行を制限するために分散ロックが使用されます。キャッシュ ミドルウェア システムとして、redis はこの種の分散ロック メカニズムを提供できます。

本質は、redis のピットを占有することです。他のプロセスがそのピットを占有しようとするとき、彼らはすでにピットを占有していることに気づきます。ピットが占有されています。占有されている場合は、しばらく待って、後でもう一度試してください

# 一般的に、運用環境で使用できる分散ロックは次の点を満たす必要があります:

相互排除、相互排他はロックの基本機能です。同時にロックを保持して重要な操作を実行できるのは 1 つのスレッドだけです。
  • タイムアウト解除、タイムアウト解除も必要です。ロックの機能を使用すると、MySQL InnoDB エンジンの
  • innodb_lock_wait_timeout
  • 設定を比較して、タイムアウト解除による不必要なスレッドの待機とリソースの浪費を防ぐことができます。分散環境での 再入性も同じです。ノード 同じスレッドがロックを取得した場合でも、リクエストは再び成功する可能性があります;
実装方法

SETNX を使用して実装

SETNX の使用方法は:

SETNX key value

. キー key が存在しない場合のみ、key key の値が value に設定されます. key key が存在する場合、SETNX何もアクションを起こしません。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>boolean result = jedis.setnx(&quot;lock-key&quot;,true)== 1L; if (result) { try { // do something } finally { jedis.del(&quot;lock-key&quot;); } }</pre><div class="contentsignin">ログイン後にコピー</div></div>この解決策には致命的な問題があります。つまり、スレッドがロックを取得し、何らかの異常な要因 (ダウンタイムなど) によりロック解除操作を正常に実行できなくなると、ロックは決して解放されなくなります。

この目的のために、このロックにタイムアウト期間を追加できます

SET キー値 EX 秒

の実行の効果は、SETEX キー秒の実行と同等です。 value##SET キー値 PX ミリ秒

の実行の効果は、

PSET キー ミリ秒値

String result = jedis.set("lock-key",true, 5);
if ("OK".equals(result)) {
    try {
        // do something
    } finally {
        jedis.del("lock-key");
    }
}
ログイン後にコピー
の実行と同等です。ソリューションは完璧に見えますが、実際にはまだ問題があります。

特定のスレッド A がロックを取得し、有効期限を 10 秒に設定し、ビジネス ロジックの実行に 15 秒かかると想像してください。このとき、スレッド A が取得します。 ロックは Redis の有効期限機構によりすでに自動的に解放されています。

スレッド A がロックを取得し、10 秒が経過すると、変更されたロックが他のスレッドによって取得されている可能性があります。スレッド A がビジネス ロジックの実行を終了し、ロック解除 (

DEL キー

) の準備をすると、他のスレッドによって取得されたロックを削除できます。

したがって、最良の方法は、ロックを解除するときに、ロックが自分のものであるかどうかを判断することです。key

uniqueValue を設定するときに、値を一意の値に設定できます (ランダムな値、UUID、またはマシン番号とスレッド番号の組み合わせ、署名など)。 ロックを解除するとき、つまりキーを削除するときは、まずそのキーに対応する値が以前に設定した値と等しいかどうかを判定し、等しい場合にはキーを削除できます

String velue= String.valueOf(System.currentTimeMillis())
String result = jedis.set("lock-key",velue, 5);
if ("OK".equals(result)) {
    try {
        // do something
    } finally {
      	//非原子操作
	      if(jedis.get("lock-key")==value){
		        jedis.del("lock-key");
        }    
    }
}
ログイン後にコピー

問題はここで一目でわかります さあ:

GET

DEL は 2 つの別個の操作です。GET 実行と DEL 実行の間のギャップで例外が発生する可能性があります。 ロック解除コードがアトミックであることを確認するだけでよい場合は、問題を解決できます。

ここでは、新しいメソッドである

Lua スクリプト

を紹介します。例は次のとおりです。

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end
ログイン後にコピー
ここで、ARGV[1]

は、キーの設定時に指定された一意の値を表します。

Lua スクリプトの原子性により、Redis がスクリプトを実行するプロセス中、他のクライアント コマンドは、Lua スクリプトが実行されるまで待機してから実行する必要があります。

有効期限がビジネス実行時間よりも長いことを確認してください

複数のスレッドがビジネス コードを同時に実行しないようにするには、次のことを確認する必要があります。有効期限がビジネス実行時間より大きいことを確認します。

ブール型属性

isOpenExpirationRenewal

を追加します。これは、スケジュールされた更新有効期限を有効にするかどうかを識別するために使用されます。

さらに、 scheduleExpirationRenewal

メソッドは、スレッドが有効期限を更新できるようにするために使用されます。

ロック コードは、ロックの取得に成功した後、isOpenExpirationRenewal を true に設定し、scheduleExpirationRenewal

メソッドを呼び出します。有効期限を更新するスレッドを開始します。

ロック解除コードはコード行を追加し、isOpenExpirationRenewal 属性を設定します。false の場合、有効期限を更新するスレッドのポーリングを停止します

Redisson の実装

ロックが正常に取得されると、スケジュールされたタスクが開始され、スケジュールされたタスクは更新のために定期的にチェックされます

このスケジュールされたスケジュールの各呼び出し間の時間差は internalLockLeaseTime / 3 で、これは 10 秒です

デフォルトでは、ロック時間は 30 秒です。実行後、30-10 = 20 秒になると更新が行われ、ロックが 30 秒にリセットされます

RedLock

クラスターでは、マスター ノードがハングアップすると、スレーブ ノードが代わりに動作しますが、クライアントには明確な認識はありません。最初のクライアントはマスター ノードのロックの申請に成功しましたが、ロックがスレーブ ノードに同期される前に、マスター ノードが突然停止したことが判明しました。その後、スレーブ ノードがマスター ノードになり、この新しいノードは内部にこのロックを持たないため、別のクライアントがロックを要求してきた場合、即座に承認されます。これにより、システム内の同じロックが 2 つのクライアントによって同時に保持されることになり、セキュリティが低下します。

Redlock アルゴリズムは、この問題を解決するためのものです。

Redlock を使用するには、複数の Redis インスタンスを提供する必要があります。これらのインスタンスは以前は互いに独立しており、マスター/スレーブ関係がありませんでした。多くの分散アルゴリズムと同様に、レッドロックもほとんどのメカニズムを使用します

ロックするとき、半分以上のノードにセット命令を送信します。半分以上のノードsetが成功する限り、ロックは成功したとみなされます。ロックを解除する場合は、全ノードにdel命令を送信する必要があります。ただし、Redlock アルゴリズムでは、エラー リトライやクロック ドリフトなどの多くの詳細な問題も考慮する必要があり、同時に Redlock は複数のノードに対して読み書きする必要があるため、Redis のパフォーマンスが低下することを意味します。

Redlock アルゴリズムは、単一の Redis ノードに基づいて導入された高可用性モードです。Redlock は、N 個の完全に独立した Redis ノードに基づいており、通常は 3 より大きい奇数です。 (通常、N は 5 に設定できます)。これにより、基本的にクラスターの各ノードが同時にダウンしないことが保証されます。

現在のクラスターに 5 つのノードがあると仮定すると、Redlock アルゴリズムを実行しているクライアントは、ロックの取得操作を完了するために次の手順を実行します。

  • クライアント レコード 現在のシステム時間 (ミリ秒単位);
  • 同じキーを順番に使用して 5 つの Redis インスタンスからロックを取得しようとします。Redis からのロックの取得を要求する場合、クライアントはネットワーク接続と応答タイムアウトを設定する必要があります。 、ネットワーク障害による問題を避けるために、タイムアウトはロックの有効期限よりも短くする必要があります;
  • クライアントは、現在の時刻からロックの取得を開始する時刻を引いた時刻を使用して、ロックの取得時間を取得します。半分からの場合に限り、上記の Redis ノードがロックを取得し、使用時間がロックの有効期限よりも短い場合、ロックは正常に取得されます。
  • ロックが取得された場合、実際の有効時間はキーは、有効時間からロックの取得に使用された時間を引いたものに等しいです。タイムアウトの可能性を減らすための時間です。
  • ロックの取得が失敗した場合、クライアントはノードを含むすべての Redis インスタンスでロックを解除する必要があります。前の操作リクエストが失敗した場合、サーバー応答メッセージが失われるのを防ぐためですが、実際のデータの追加が成功したために不整合が発生しました。

つまり、ロックの期限が 30 秒で切れ、3 つのノードをロックするのに 31 秒かかると仮定すると、当然ロックは失敗します。

Redis が公式に推奨する Java クライアントではRedisson には RedLock

https://redis.io/topics/distlock

https:/ の組み込み実装があります/ github.com/redisson/redisson/wiki

RedLock の問題:

RedLock はロックの高可用性を保証するだけで、正確性は保証しませんロックの

RedLock はシステム クロックに大きく依存する 分散システムです

Martin の RedLock に対する批判:

  • 効率向上のためシナリオでは、RedLock が重すぎます。
  • 非常に高い精度が必要なシナリオの場合、RedLock は精度を保証できません。

この記事は https://juejin.cn/post/7018968452136173576

著者: 遠い心で

から転載しましたプログラミング関連の詳細については、プログラミング ビデオ をご覧ください。 !

以上が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衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の 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 10:12 PM

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

Centos RedisでLUAスクリプト実行時間を構成する方法 Centos RedisでLUAスクリプト実行時間を構成する方法 Apr 14, 2025 pm 02:12 PM

Centosシステムでは、Redis構成ファイルを変更するか、Redisコマンドを使用して悪意のあるスクリプトがあまりにも多くのリソースを消費しないようにすることにより、LUAスクリプトの実行時間を制限できます。方法1:Redis構成ファイルを変更し、Redis構成ファイルを見つけます:Redis構成ファイルは通常/etc/redis/redis.confにあります。構成ファイルの編集:テキストエディター(VIやNANOなど)を使用して構成ファイルを開きます:sudovi/etc/redis/redis.conf luaスクリプト実行時間制限を設定します。

Redisコマンドラインの使用方法 Redisコマンドラインの使用方法 Apr 10, 2025 pm 10:18 PM

Redisコマンドラインツール(Redis-Cli)を使用して、次の手順を使用してRedisを管理および操作します。サーバーに接続し、アドレスとポートを指定します。コマンド名とパラメーターを使用して、コマンドをサーバーに送信します。ヘルプコマンドを使用して、特定のコマンドのヘルプ情報を表示します。 QUITコマンドを使用して、コマンドラインツールを終了します。

Redisカウンターを実装する方法 Redisカウンターを実装する方法 Apr 10, 2025 pm 10:21 PM

Redisカウンターは、R​​edisキー価値ペアストレージを使用して、カウンターキーの作成、カウントの増加、カウントの減少、カウントのリセット、およびカウントの取得など、カウント操作を実装するメカニズムです。 Redisカウンターの利点には、高速速度、高い並行性、耐久性、シンプルさと使いやすさが含まれます。ユーザーアクセスカウント、リアルタイムメトリック追跡、ゲームのスコアとランキング、注文処理などのシナリオで使用できます。

Redisの有効期限ポリシーを設定する方法 Redisの有効期限ポリシーを設定する方法 Apr 10, 2025 pm 10:03 PM

Redisデータの有効期間戦略には2つのタイプがあります。周期削除:期限切れのキーを削除する定期的なスキャン。これは、期限切れの時間帯-remove-countおよび期限切れの時間帯-remove-delayパラメーターを介して設定できます。怠zyな削除:キーが読み取られたり書かれたりした場合にのみ、削除の有効期限が切れたキーを確認してください。それらは、レイジーフリーレイジーエビクション、レイジーフリーレイジーエクスピア、レイジーフリーラジーユーザーのパラメーターを介して設定できます。

Debian Readdirのパフォーマンスを最適化する方法 Debian Readdirのパフォーマンスを最適化する方法 Apr 13, 2025 am 08:48 AM

Debian Systemsでは、Directoryコンテンツを読み取るためにReadDirシステム呼び出しが使用されます。パフォーマンスが良くない場合は、次の最適化戦略を試してください。ディレクトリファイルの数を簡素化します。大きなディレクトリをできる限り複数の小さなディレクトリに分割し、Readdirコールごとに処理されたアイテムの数を減らします。ディレクトリコンテンツのキャッシュを有効にする:キャッシュメカニズムを構築し、定期的にキャッシュを更新するか、ディレクトリコンテンツが変更されたときに、頻繁な呼び出しをreaddirに削減します。メモリキャッシュ(memcachedやredisなど)またはローカルキャッシュ(ファイルやデータベースなど)を考慮することができます。効率的なデータ構造を採用する:ディレクトリトラバーサルを自分で実装する場合、より効率的なデータ構造(線形検索の代わりにハッシュテーブルなど)を選択してディレクトリ情報を保存およびアクセスする

See all articles