分散ロックに Redis を使用する方法をいくつ知っていますか? 2つ紹介します

分散ロックに Redis を使用する方法をいくつ知っていますか? 2つ紹介します

[[318373]]

この記事では、次の内容について説明します。

1. 分散ロックとは何ですか?

2. 解決策

  • 2.1 全体的な考え方
  • 2.2 解決策1
  • 2.3 解決策2

3. まとめ

Redis は、いくつかの単純なデータ型を持つキー/値データベースです。今では分散ロック、電流制限ツール、メッセージキューになってしまい、もうダメになりそうです。しかし、Redis は、その極めて高いパフォーマンスと使いやすさにより、多くの場面で開発者に愛されています。

インタビュー中、Redis について話すとき、多くの人の最初の反応はキャッシュです。実際、キャッシュに加えて、Redis には豊富な使用シナリオが数多くあります。今後、Song Ge はこれらの使用シナリオを 1 つずつ皆さんと共有する予定です。

今日は、分散ロックに Redis を使用する簡単な例を見てみましょう。

1. 分散ロックとは何ですか?まず、問題のシナリオを見てみましょう。

たとえば、単純なユーザー操作、つまりユーザーのステータスを変更するスレッドでは、まずデータベースからユーザーのステータスを読み取り、次にメモリ内で変更し、変更が完了したらそれを保存し直します。単一スレッドではこの操作は問題ありませんが、マルチスレッドでは、読み取り、変更、保存の 3 つの操作はアトミック操作ではないため、マルチスレッドで問題が発生します。

この問題を解決するには、ロックが必要です。誰もがロックについてよく知っておく必要があります。 Java の synchronized および ReentrantLock 再入可能ロックは一般的ですが、これらのロックはローカル ロックです。現在、マイクロサービスと分散システムの考え方が人気です。このようなシステムでは、ローカル ロックだけでは明らかに不十分なので、誰もが分散環境でロックの問題を解決する方法を見つけようとしています。分散ロック問題を解決する方法は数多くあります。分散ロックの問題を解決するには、MySQL、ZK、または Redis を使用できます。ここでは主に、Redis を通じて分散ロックの問題を解決する方法について説明します。

2. 解決策

2.1 全体的な考え方

「分散ロックの背後にある考え方は非常にシンプルです。ライン シティが参入すると、最初に席を確保します。他のライン シティが運用を開始したときに、すでに誰かが席を確保していることがわかったので、諦めるか、後でもう一度試すことになります。」

Redis では、プレースホルダーは通常、setnx 命令を使用します。最初に到着したスレッドがプレースホルダーを取得します。スレッドの操作が完了すると、 del 命令が呼び出され、その場所が解放されます。同時に、デッドロックを防ぐために、通常はロックに有効期限を追加し、有効期限が切れると自動的に解除されます。

この考えに基づいて、2 つの異なる実装方法を見てみましょう。

2.2 解決策1

上記のアイデアに基づいて、setnx と expire を使用して分散ロックを実装できますが、setnx と有効期限の設定 expire は 2 つの操作です。これら 2 つの操作を一緒に実行した場合、それらはアトミックにはなりません (独自の Lua スクリプトを作成しない限り)。この問題を解決するために、Redis 2.8 以降では、setnx と expire を 1 つのコマンド set で一緒に実行できるようになりました。セットにはもう 1 つのパラメータがあります。

図からわかるように、キー/値の後には、有効期限を秒単位で示す EX 5 (有効期限をミリ秒単位で示す PX) があり、最後の NX は、k1 が存在しない場合はコマンドが正常に実行され、それ以外の場合は失敗することを意味します。これは、setnx の効果に相当します。

したがって、ロックを次のようにカプセル化します。

  1. パブリッククラスLockTest{
  2. 公共 静的void main(String[] args) {
  3. Redis の redis = new Redis();
  4. redis.execute (jedis->{
  5. 文字列セット= jedis。 ( "k1" "v1" 、新しい SetParams().nx().ex(5) を設定します);
  6. if ( set != null && "OK" .equals( set )) {
  7. //誰も席に着いていない
  8. jedis.set ( "名前" , "javaboy" );
  9. 文字列= jedis.get( "name" );
  10. システム。 .println(名前)を出力する
  11. jedis.del( "k1" ); //リソースを解放する
  12. }それ以外{
  13. //誰かが席を占有しているので、操作を停止/一時停止します
  14. }
  15. });
  16. }
  17. }

上記のコードでは、アイデアに焦点を当てており、コードの詳細を掘り下げる必要はありません。

  1. まず、Redis インスタンスを構築し、次に独自にカプセル化したメソッドである execute メソッドを呼び出します。目的は、Jedis 接続プールを構成し、使用されたリソースを時間内にリサイクルすることです。この部分をテストする場合は、作成した Jedis インスタンスを直接使用することができ、効果は同じです。
  2. jedis の set メソッドを呼び出します。 3 番目のパラメータに注意してください。 nx と有効期限を 5 秒に設定します。これは、setnx コマンドと expire コマンドの組み合わせと同等です。
  3. set コマンドが正常に実行された場合、if ステートメント内に独自の処理を記述できます。ロックを取得できない場合は、遅延メッセージ キューに入り、しばらく停止してから再試行できます (Redis を使用して遅延メッセージ キューを実装する方法については、Song Ge が後の記事で紹介します)。

2.3 解決策2

上記のコードはかなり長いので、もっと簡単な方法はありますか?もちろんありますよ!それがレディソンです。

Jedis の元のアプリケーションと比較して、Redisson は Redis リクエストのカプセル化をさらに進め、直接使用できるロックに対応するメソッドも提供しています。

  1. 設定 config = new Config();
  2. //Redis の基本接続情報を設定する
  3. config.useSingleServer().setAddress( "redis://127.0.0.1:6379" ).setPassword( "123" );
  4. //RedissonClientオブジェクトを取得する
  5. RedissonClient redisson = Redisson.create (config);
  6. //ロックオブジェクトのインスタンスを取得する
  7. RLock ロック = redisson.getLock( "ロック" );
  8. 試す {
  9. //ロックを取得する
  10. ブール値 b = lock.tryLock(500, 1000, TimeUnit.MILLISECONDS);
  11. (b) の場合 {
  12. //ロックを取得してビジネスを書き始める
  13. RBucket<Object> バケット = redisson.getBucket( "javaboy" );
  14. バケットを設定します( "www.javaboy.org" );
  15. オブジェクト o = bucket.get();
  16. システム.out.println (o) ;
  17. }それ以外{
  18. System.out.println ( "ロックを取得できませんでした" ) ;
  19. }
  20. } キャッチ (InterruptedException e) {
  21. e.printStackTrace();
  22. ついに
  23. //ロックを解除する
  24. ロックを解除します。
  25. }

このコードでは、核となるのは lock.tryLock(500, 1000, TimeUnit.MILLISECONDS); です。最初のパラメーターはロックを試行するための待機時間で、500 ミリ秒です。2 番目のパラメーターは、ロック タイムアウトが 1000 ミリ秒であることを示します。つまり、ロックは 1000 ミリ秒後に自動的に期限切れになります。

友人たちは、これがソリューション 1 で設定したパラメータと同じであることに気付きました。実際、アイデアは変更されていません。 Redisson は、私たちが書いたロック関連のメソッドをカプセル化するだけです。

3. まとめ

もちろん、ここではロックの考え方と、単一の Redis マシンでロックする方法を簡単に紹介するだけにします。後ほど、Song 兄弟が Redis クラスターをロックする方法を説明します。

<<:  クラウド コンピューティング プロバイダー間でネットワーク パフォーマンスがどのように異なるか

>>:  分散システムにおける「ゴースト再発」を解決するにはどうすればよいでしょうか?

推薦する

フォーブス 2019 クラウド 100: ストライプは引き続きトップ、上位 5 社は刷新

テクノロジーの最もホットな分野であるクラウド コンピューティングは、デジタル時代におけるコミュニケー...

クラウド プラットフォームを「より適切に管理」するにはどうすればよいでしょうか?ファーウェイのクラウド集中運用・保守が企業のイノベーションを加速

デジタル化の波は世界の経済情勢を一変させており、デジタル経済は世界の持続可能な成長の新たな原動力にな...

ウェブサイトのキーワードランキングが下がった理由と解決策をまとめます

このタイトルを見ると、誰かが以前に理由をまとめたことに誰もが間違いなく気づいたでしょうが、Xiao ...

Hawkhost-VPS 8月/ダラスの60%オフプロモーション

Hawkhost は、OpenVZ ベース、バースト メモリ搭載、データ センターはダラスの VPS...

WordPress コミュニティに商用有料テーマがさらに必要なのはなぜですか?

有料テーマが無料テーマよりも優れている点は何ですか?より美しい外観とより強力な機能ほとんどの無料テー...

74 個の中国語トップレベルドメイン名:「先駆的」か「恥ずかしい」か?

[すべてがうまくいけば、Zodiac Technology を含む申請者は「金鉱」を掘り当てることに...

Pacificrack: 中秋節フラッシュセール、複数の高構成 VPS が年間 13.15 ドルから

中秋節期間中、Pacificrack は VPS フラッシュセールを開始しました。多くの高構成 VP...

desivps: 米国 VPS (ロサンゼルス)/オランダ VPS、年間 30 ドルから、KVM 仮想化/2g メモリ/1 コア/20g SSD/2.5T トラフィック/1Gbps 帯域幅

昨年設立されたインドのホスティング会社 desivps は、米国ロサンゼルスとオランダのアムステルダ...

旅行ウェブサイト向けに価値の高いオリジナル記事を執筆することは、新鮮な水の源です。

周知のとおり、Baidu アルゴリズムの継続的なアップグレードとユーザー エクスペリエンスに対する要...

OracleとIDCが共同でSaaS市場の業界動向レポートを発表

ビッグデータ、クラウドコンピューティング、ソーシャルエンジンを中心とした革新的なテクノロジーは、企業...

オラクル、Oracle Exadata Cloud Service X8Mを発表

Oracle は Oracle Exadata Cloud Service X8M をリリースし、現...

vikinglayer -$7/KVM/4G メモリ/90g SSD/4T トラフィック/ダラス

vikinglayer は drserver.net のサブブランドです。1999 年から運営されて...

arkecxはどうですか?ベトナムのハノイにあるクラウドサーバーの簡単なレビュー

市場に出回っているベトナムのクラウドサーバーは多くなく、帯域幅が大きく使いやすいものもほとんどありま...

eBPFテクノロジーの威力の予備的調査

G バンク アプリケーションにフルスタック クラウドが使用されるケースが増えるにつれて、クラウド ア...

ロングテールキーワードを使用して新規サイトの SEO 最適化の速度を向上させる方法

ウェブマスターとして、誰もが新しいウェブサイトにできるだけ早くトラフィックを集め、できるだけ早くラン...