ダークホースレビュー09 フラッシュセール機能概要

 1.全体的な業務プロセス

1.1 redis判定処理(シングルスレッド)

1. まず注文 ID とユーザー ID を取得し、Lua スクリプトを呼び出して Redis 操作を実行します。Lua には、購入資格/在庫の適正性の判断、在庫の差し引きと発注、および Stream への注文メッセージの送信が含まれます。

2. ストリームはメッセージ キューを形成し、例外は自動的に保留リストに入れられます。

1.2 スレッド処理(複数のスレッドが交代で実行)

1. スレッドはメッセージ キューを読み取ります (メッセージ キューの読み取り)。メッセージを読み取ることができる場合は読み取りを続けます。注文メッセージを読み取る場合は、メッセージの内容を解析し、注文関数 3 を呼び出してデータベースに書き込み、応答します。確認 ack; if 例外が発生した場合は、保留リストのステップ 2 に進みます。

2. 保留リストを処理し、メッセージを解析し、注文し、処理します。例外がある場合は、このサイクルを繰り返して処理を続行します。処理が完了するまで、プロセスは終了します。

3. Redisson 分散ロックを追加し、注文データベースの作成操作を呼び出します。

2. どのような問題が解決されましたか?

2.1. 売られすぎ問題 --> 楽観的ロック

楽観ロックにより、在庫をバージョン番号として使用し、在庫が0より大きい限り注文を許可することができます(後で解決策があります)

lua スクリプトのコード

2.2 1 人、1 注文 -> セットを維持、ユーザー ID + クーポン ID を保存、重いジャッジ

sismember は、ユーザー ID とクーポン ID のレコードがコレクション内に同時に存在するかどうかを判断します。

セット構成により、ユーザー数が多くても重複が最小限に抑えられ、存在判定効率も高くなります。

2.3 Lua スクリプトの頻繁な読み取りを避ける

静的リソースとして定義されているため、Lua スクリプトを繰り返し読み取らなくても、いつでもアクセスできます。

2.3 分散ロック Redisson を使用する理由

分散ロックにより、クラスター モードのさまざまなサーバー JVM 上のロックの一意性が保証されます。

その後、Redisson は再入性を保証できるハッシュ構造を使用しました。

Redisson は、2.4 および 2.5 の問題を内部で自動的に解決します。

2.4 (この問題は自己実装でのみ発生します) 分散ロック クラッシュ デッドロック --> 有効期限を設定し、lua スクリプトのアトミック性を確保

有効期限により、ロックの有効期限が切れ、サービスがダウンした後にロックが解放されます。

Lua スクリプトは、有効期限が追加される前にロックがクラッシュしないことを保証します。

Redisson は有効期限とロック (lua) のアトミック操作を内部で自動的に実装するため、個別に実行されることはなく、デッドロックが発生しません。

2.5 (この問題は自己実装でのみ発生します) マルチスレッドによる分散ロックの誤った削除 --> スレッド識別の決定 + 原子性の確保 Lua スクリプト

ロックの一意のスレッド ID を確認します。自分のものでない場合は、削除しないでください。

Lua はアトミック性を確保し、ID 判定とロック削除の間のギャップを回避します。

Redisson にはロックを自動的に更新するウォッチドッグ メカニズムがあるため、ロックの有効期限が切れて他のスレッドがロックを取得し、誤って削除するという問題は発生しませんサービスがダウンし、ウォッチドッグ メカニズムが停止した後でのみ、ロックの有効期限が切れますが、これは誤って削除されたという問題ではありません (サービスはブロックされていますが、ダウンしていません)。

 2.6 Redisson は再入力、再試行、自動更新が可能

リエントラント: ロックの最下層はハッシュ構造であり、ハッシュの名前は、ハッシュのキー (フィールド) はスレッド名、値はリエントラントの数です。

ロックの取得回数が 1 回増加し、ロックの完了回数が 1 回減り、回数が 0 になった場合のみスレッドはロックを解放します。

再試行可能: サブスクリプションを公開します。ロック メッセージを購読する。他のスレッドがロックを解放すると、他のスレッドにロックを取得するよう通知するメッセージが発行されます。残りの再試行時間 waitTime があります。すべてのロック取得時間の合計がこのしきい値を超えると、再試行は中止されます。まだ再試行時間が残っている場合は、解放を待ち続けてから取得します。待機時間リリースは現在の残りの再試行時間です。待ちきれないなら、待たないでください。

 自動更新: ウォッチドッグ、リトライ時間 (デフォルトは 30 秒) を毎回 30 秒からリセットする機能。次に、再帰してワイヤレスの更新を実現します。

3. いくつかのデータ構造

Redis で 3.1

3.1.1 お一人様1注文セット

オーダー ID とユーザー ID を含む Redis のセット構造を使用する

redis.call('sismember', orderKey, userId) == 1)

3.1.2 メッセージキューストリーム

--3.5 Redis ストリーム キューにメッセージを送信する、xadd stream.orders * k1 v1 k2 v2... 
redis.call('xadd', 'stream.orders', '*', 'userId', userId, ' voteId',バウチャー ID、「ID」、オーダー ID)

3.1.3 文字列を使用した在庫数の計算

redis.call('get', StockKey)) <= 0)

mysqlの3.2

3.2.1 注文の完了

受信した注文を維持する

3.2.2 クーポンとフラッシュセールクーポン

クーポンデータ

4. 改善点(個人的な意見)

4.1 現在のプロジェクトではシングルポイント Redis を使用していますが、Redis の同時実行性を向上させるために、後で Redis クラスター戦略の導入を検討します。

4.2 現在、メッセージ キューは Redis の Stream タイプを使用していますが、プロジェクトの堅牢性を向上させたい場合は、将来的にプロフェッショナル MQ に切り替えることができます。

5. サービスクラスター

idea に付属の機能を使用して、プロジェクトの複数のシミュレートされたクラスターを開始し、nginx を使用してリバース プロキシと負荷分散を担当します。

nginx は、起動した複数のノードにリバース プロキシを実行します。

おすすめ

転載: blog.csdn.net/m0_50973548/article/details/135119384