Redisは在庫超過問題の解決例を説明します。
商品と注文サービスの間にMQを使用します。
商品サービスの在庫が変化した場合、MQを通じて注文サービスの在庫の変化を通知します。
オリジナルの同期プロセス商品情報(商品サービスの呼び出し)を調べる 合計価格を計算する(注文書の詳細を生成する) 商品サービスは在庫品(商品サービスの呼び出し) を差し引いています。オーダー入庫(注文生成) 多くの注文が商品の在庫を差し引き、未決済になる可能性があります。これはバックグラウンドスクリプトが必要です。しばらくの間に支払っていない注文の在庫を釈放して、注文をキャンセルして、即時に在庫を差し引いて、同時差 です。 1、3段階商品サービス、商品サービスのdb、2、4段階注文サービスを操作して、注文サービスのdbを操作します。 異なるサービスのdbへのアクセスを避けるには、原則として同じサービスは自身のサービスのdbのみを操作することができます。
MQ非同期化
まず第4ステップだけを非同期にすることを考えます。
分析
2、4はすべてdbを操作するので、第4歩はもう待ってなくて、1、2、3が成功したらすぐにユーザーにフィードバックします。
その後、メッセージを通じてサービスを非同期的に注文し、第4ステップで注文を失敗したら、再度テストして、注文書を再生成しようとします。MQのメッセージもトレースできます。
注文書の作成が完了した後、待機状態になり、サービスはメッセージ・キューにイベント
つまり注文サービスは外部にメッセージを送ります。注文書を作成して、MQから購読サービスに転送します。
商品サービスが注文書作成のメッセージを受け取ったら、在庫の差し引き操作を行います。ここでは、いくつかの不可抗因によって在庫の控除が失敗した可能性があります。成功するかどうかにかかわらず、商品サービスはMQに在庫メッセージを送信します。メッセージの内容は在庫の結果を差し引きます。
注文サービスは在庫を差し引いた結果を購読し、このメッセージを受信した後:在庫を引き締めることに成功すれば、注文の状態を確認済みに変更します。即ち注文は成功しました。 もし在庫を差し引いて失敗したら、注文の状態をキャンセルしました。つまり注文失敗です。
上記モデルの要求を実現するには、信頼できる情報伝達が必要です。サービスからのメッセージは、必ずMQに受信されます。 ユーザが体験した変化に対して、フロントエンドは、待ち行列中のインターフェースと組み合わせる。 商品/注文サービスはすべて非同期化しています。秒殺のシーンに適しています。
非同期設計在庫品はRedisに を保存します。受信したRedisは在庫が十分かどうかを判断し、Redisの中の在庫 を減らします。注文サービスは注文書を作成してデータベースに書き込んで、メッセージを送ります。
注文書の支払いが成功したら、出庫過程があります。この過程がある以上、出庫失敗の可能性があります。
在庫は二つあります。 キャッシュレス層 データベースmysql階 顧客サービスに5つの在庫が追加されると、キャッシュレスとデータベースmysqlの層は5つの在庫を追加しなければなりません。分散式事務の最終的な一致を使って満足します。 注文書が生成されると、在庫を差し引いて先にredis在庫を控除し、もし控除が成功すれば、注文書を作成して支払います。この過程でmysql在庫を差し引いてはいけません。 フレディ在庫が終わったら、この商品は注文できなくなります。注文が失敗したら、外層のものをブロックします。 は第2段階でredis在庫を差し引いて成功した後、注文書を作成し、支払いを行い、私の注文センターに戻ります。出庫過程があります。 出庫過程はMQ非同期結合のタスク・キューであり、このプロセスはmysql在庫を差し引いたものである。 もしmysqlの在库を挂けて成功するならば、出庫は成功して、注文の全体の流れを完成して、出荷の状态に入ります。 もしmysqlの在庫を掛けて失敗すれば、出庫は失敗して、一連の操作を行います。 注文状況をキャンセル に変更しました。フレディ在庫を返します。 払い戻し redis在庫とmysql在庫
お支払いの前にプリペイドです。インベントリをロックする過程です。
支払った後は本当に掛けます。mysql在庫を引いて、在庫が最終的に一致することを保証します。
ただし、極端な場合にはデータの不一致があります。もしredis在庫=mysql在庫があれば、問題がないです。 もしredis在庫があれば、超売り問題はありませんが、実際に在庫がありますが、売っていない場合があります。 もしredis在庫>mysql在庫があれば、超売り、超売り注文は出庫中に失敗します。
このように全体的には問題がありません。mysqlデータベース層は在庫が最終的に問題にならないように保証します。
問題
データベース在庫とredis在庫が一致しない場合、どうやって検査しますか?
もし不一致が検出されたら、どうやって同期しますか?
いい案が思いつかない
暴力的な方法は、低ピーク期を探して、例えば午前1時、周期的に強制的にカバーします。しかし、極端な場合は同期後の不正確さがあります。例えば同期中に、ちょうど一つの注文が支払われています。この注文が支払われた後、出庫の過程で、mysqlの在庫は差し引かれましたが、redisの在庫は差し引かれていません。
これはデータベース同期キャッシュの更新メカニズムの問題です。
整合性に属する論理設計の問題
システムの複雑さによって、大きいシステムほど細かく分解されます。
例えば、控除数はまた一つの列に入れてもいいし、キャッシュの中に入れてもいいです。同時にカウントがあります。直接カウントを読めばいいです。
例えば、モンゴに入れて、すでに出荷待ちの数量を支払っても、普通はそんなに大きくないです。countを一回やっても、損失はいくらもありません。
したがって、一般的なシステムは、データチェーンの間違いを完全に保証することはできませんが、補償が必要です。エラーを訂正することができます。
間違いのない値段を保障するには明らかに大きすぎる。
同期にはリフレッシュの仕組みがあり、タイミングを決めたり、MQを通したり、監視が同期にならないなどがあります。
キャッシュデータの鮮度を保証するともいいます。
普通はあまり時間がかかりません。30分、数分で可能です。場面によって違います。
12306
列車の切符を買う12306は夜の時間は全部切符を買うことができません。この時間は在庫を同期させて、データベースの在庫をredis在庫に同期させます。でも、列車のチケットを買うなど、注文が発生する前に、実際の在庫を差し引いて、つまりmysqlの在庫を差し引かなければなりません。
列車の切符を買うのは買い物と違って、買い物はお金を払ってから出庫することができます。しかし、切符を買うのは、支払いの前に出庫しなければなりません。ですから、出庫の過程を前倒しして、出庫に成功してこそ、注文書を作成できます。同じようにレディスの在庫を導入します。
キャッシュの中の在庫を差し引いて、成功後にやっとmysqlの中の在庫を差し引いてもいいです。
キャッシュの中の在庫を差し引いて失敗すれば、外に隠れて在庫不足に戻ります。これらの要求はmysqlに刺さらず、多くの請求圧力を遮断します。
redis在庫はmysql在庫と一致しません。極端な場合は間違いなくあります。在庫の同期が必要です。 キャッシュ在庫がデータベース在庫より多いと、チケットがあると調べられますが、注文できないと在庫が足りないと言っています。この場合、データベースの圧力が大きすぎると思いますが、12306は他の手段でこの問題を回避するべきです。 キャッシュ在庫がデータベースキャッシュより少ない場合、問題がなく、チケットがあるだけですが、販売されていない場合は、在庫の同期が完了したら、明日また正確になります。 この記事では、Redisの在庫超過問題の解決例について説明します。これまでの記事を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。
商品サービスの在庫が変化した場合、MQを通じて注文サービスの在庫の変化を通知します。
オリジナルの同期プロセス
// MySQL
//
SeckillVouchers seckillVouchers = seckillVouchersMapper.selectVoucher(voucherId);
AssertUtil.isTrue(seckillVouchers == null, " ");
//
AssertUtil.isTrue(seckillVouchers.getIsValid() == 0, " ");
//
seckillVouchersMapper.save(seckillVouchers);
注文書が生成された時に直接在庫を差し引いて、これは一番原始的な在庫控除案です。比較的簡単ですが、問題があります。MQ非同期化
まず第4ステップだけを非同期にすることを考えます。
分析
2、4はすべてdbを操作するので、第4歩はもう待ってなくて、1、2、3が成功したらすぐにユーザーにフィードバックします。
その後、メッセージを通じてサービスを非同期的に注文し、第4ステップで注文を失敗したら、再度テストして、注文書を再生成しようとします。MQのメッセージもトレースできます。
注文書の作成が完了した後、待機状態になり、サービスはメッセージ・キューにイベント
Order Created
をリリースする。つまり注文サービスは外部にメッセージを送ります。注文書を作成して、MQから購読サービスに転送します。
商品サービスが注文書作成のメッセージを受け取ったら、在庫の差し引き操作を行います。ここでは、いくつかの不可抗因によって在庫の控除が失敗した可能性があります。成功するかどうかにかかわらず、商品サービスはMQに在庫メッセージを送信します。メッセージの内容は在庫の結果を差し引きます。
注文サービスは在庫を差し引いた結果を購読し、このメッセージを受信した後:
上記モデルの要求を実現するには、信頼できる情報伝達が必要です。サービスからのメッセージは、必ずMQに受信されます。
非同期設計
注文書の支払いが成功したら、出庫過程があります。この過程がある以上、出庫失敗の可能性があります。
在庫は二つあります。
お支払いの前にプリペイドです。インベントリをロックする過程です。
支払った後は本当に掛けます。mysql在庫を引いて、在庫が最終的に一致することを保証します。
ただし、極端な場合にはデータの不一致があります。
このように全体的には問題がありません。mysqlデータベース層は在庫が最終的に問題にならないように保証します。
問題
データベース在庫とredis在庫が一致しない場合、どうやって検査しますか?
もし不一致が検出されたら、どうやって同期しますか?
いい案が思いつかない
暴力的な方法は、低ピーク期を探して、例えば午前1時、周期的に強制的にカバーします。しかし、極端な場合は同期後の不正確さがあります。例えば同期中に、ちょうど一つの注文が支払われています。この注文が支払われた後、出庫の過程で、mysqlの在庫は差し引かれましたが、redisの在庫は差し引かれていません。
これはデータベース同期キャッシュの更新メカニズムの問題です。
整合性に属する論理設計の問題
= -
もちろんこの中には他の案もあります。一致性の高さを考慮して、簡単で複雑な案が使えます。システムの複雑さによって、大きいシステムほど細かく分解されます。
例えば、控除数はまた一つの列に入れてもいいし、キャッシュの中に入れてもいいです。同時にカウントがあります。直接カウントを読めばいいです。
例えば、モンゴに入れて、すでに出荷待ちの数量を支払っても、普通はそんなに大きくないです。countを一回やっても、損失はいくらもありません。
したがって、一般的なシステムは、データチェーンの間違いを完全に保証することはできませんが、補償が必要です。エラーを訂正することができます。
間違いのない値段を保障するには明らかに大きすぎる。
同期にはリフレッシュの仕組みがあり、タイミングを決めたり、MQを通したり、監視が同期にならないなどがあります。
キャッシュデータの鮮度を保証するともいいます。
普通はあまり時間がかかりません。30分、数分で可能です。場面によって違います。
12306
列車の切符を買う12306は夜の時間は全部切符を買うことができません。この時間は在庫を同期させて、データベースの在庫をredis在庫に同期させます。でも、列車のチケットを買うなど、注文が発生する前に、実際の在庫を差し引いて、つまりmysqlの在庫を差し引かなければなりません。
列車の切符を買うのは買い物と違って、買い物はお金を払ってから出庫することができます。しかし、切符を買うのは、支払いの前に出庫しなければなりません。ですから、出庫の過程を前倒しして、出庫に成功してこそ、注文書を作成できます。同じようにレディスの在庫を導入します。
キャッシュの中の在庫を差し引いて、成功後にやっとmysqlの中の在庫を差し引いてもいいです。
キャッシュの中の在庫を差し引いて失敗すれば、外に隠れて在庫不足に戻ります。これらの要求はmysqlに刺さらず、多くの請求圧力を遮断します。
redis在庫はmysql在庫と一致しません。極端な場合は間違いなくあります。在庫の同期が必要です。