そうですね、ローカル システムで作業するときは常に、すべてがバターのように機能します。それが、私たちが 「127.0.0.1 に勝る場所はない」 と呼ぶ理由ですが、現実に目覚めてください
まあ、本番環境では必ずしも期待どおりに動作するとは限りません。主に、アプリケーションの複数のインスタンスを実行している場合です。
?ご覧のとおり、アプリケーションの複数のインスタンスが実行されており、クライアントが DB 内でユーザーを有料ユーザーとしてマークするリクエストを行ったとします。
大丈夫そうですよね?今のところ問題ありません。
そうですね、今のところは問題ありません。しかし、次のようなビジネス ロジックを書きたい場合はどうなるでしょうか:-
⚡️ ご存知のとおり (ここでは MySQL を使用していると仮定します)、MySQL DB は ACID に準拠しており、これはすべてのクエリがアトミックで分離されることを意味します。これは、MySQL クエリがアトミックな方法で実行され、成功するか失敗するかを意味します。ただし、途中で終了することはありません。
?しかし、ここで問題が 1 つあります。考えて、考えて....
ステップ 2 で支払いをキャンセルするリクエストがもう 1 つあり、そのクエリが最初に実行されてユーザーが無料としてマークされ、次にステップ 3 が実行されてユーザーが有料としてマークされた場合はどうなりますか。
??万歳、ユーザーは料金を支払うことなく当社の製品にアクセスできるようになりました。
✅ 救世主、ロックスの登場
?ロックは、一度に 1 つのスレッドのみがクリティカル セクション (複数のワーカー、つまりスレッドによってアクセスされるべきではないコードのブロック) に入ることができる構造です
したがって、操作の完了前にロックを取得し、完了後に解放します。-
ここで問題が発生します。それは、メモリ ロック データ構造またはメモリ ベースのロックを使用する場合、それがアプリケーションの 1 つのインスタンスに適格になるということです。同じコードを実行し、DB 内で更新している他のインスタンスはどうなりますか?
分散ロックの概念が登場します
ここでのロックは集中サービスとして機能し、サービスの 1 つのインスタンスがロックを取得すると、他のインスタンスは同じキーを使用できなくなります。
支払いサービスではどのようなキーがここにある可能性がありますか?
?ユーザーが支払いを行う場合、キーは = "PAYMENT_" + user_id + amount
の組み合わせになります。これはユーザーごとに一意になります。そして、このキーは、ユーザーが支払いを行ったり、支払いをキャンセルしたりしても同じままになります。したがって、どちらかのアクションが同じキーを取得しようとするため、一方のアクションが発生しているときは、他のアクションを続行できません。
?一体何だ キー、ロックの取得、ロックの解除。そして最も重要なのは、Redis がどのように使用されているのかということです。
しかし、単一の Redis インスタンスにはいくつかの問題があります:-
?つまり、マスターでロックが取得され、レプリカとの通信中にマスターがレプリカと同期する前にダウンした場合です。レプリカはマスターになり、以前にマスターで取得したものと同じキーのロックを取得できるようになります。
サービスの 2 つのインスタンスは、2 つのインスタンス (マスター レプリカ) がある場合でも、Redis 上のロックを取得できます。
ロックの取得:- ロックの有効期限を指定して複数の Redis インスタンスのロックを取得しようとします
ロックの検証:- 主要な Redis インスタンスがクライアントに対してロックを取得した場合、ロックは取得されたものとみなされます
ロックの解放:- ロックを解放すると、すべてのインスタンスがロックを解放します
はい、それだけです。
❤️ お読みいただきありがとうございます。このような記事をさらにご覧いただくためにニュースレターを購読してください:- https://www.serversidedigest.com/
詳細情報:-
以上がRedis を使用して分散ロックを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。