ホームページ  >  記事  >  データベース  >  Redis での売れすぎ在庫の問題の解決

Redis での売れすぎ在庫の問題の解決

coldplay.xixi
coldplay.xixi転載
2021-03-18 10:49:422869ブラウズ

Redis での売れすぎ在庫の問題の解決

#製品と注文サービスの間で MQ を使用する

製品サービスの在庫が変更されると、注文サービスのインベントリは、MQ Variety を通じて通知されます。

元の同期プロセス

    製品情報のクエリ (製品サービスの呼び出し)
  1. 合計価格の計算 (注文詳細の生成)
  2. コモディティ サービスは在庫を差し引きます (コモディティ サービスを呼び出します)
  3. 注文倉庫管理 (注文を生成します)
  4. // 原始的MySQL同步流程// 判断此代金券是否加入抢购SeckillVouchers seckillVouchers = seckillVouchersMapper.selectVoucher(voucherId);AssertUtil.isTrue(seckillVouchers == null, "该代金券并未有抢购活动");// 判断是否有效AssertUtil.isTrue(seckillVouchers.getIsValid() == 0, "该活动已结束");// 插入数据库seckillVouchersMapper.save(seckillVouchers);

推奨事項 (無料): redis

注文が生成されたときに在庫を直接控除します。これは最も独創的な在庫控除計画です。比較的単純ですが、

問題があります

    多くの注文で、支払いなしで製品在庫が差し引かれる可能性があります。これには、一定期間支払われていない注文の在庫を解放し、注文をキャンセルするバックグラウンド スクリプトが必要です。
  • 即時在庫控除、同時実行差分
1. 3 ステップの製品サービス、製品サービスのデータベースの操作、2. 4 ステップの注文サービス、注文サービスのデータベースの操作。

異なるサービスのデータベースへのアクセスは避ける 同一サービスは原則として自身のサービスのデータベースのみ操作可能です。

MQ の非同期化

まず、ステップ 4 のみを非同期にすることを検討します。

分析

2 と 4 はすべてデータベース上の操作です。ステップ 4 は待機しません。ステップ 1 の成功後、すぐにユーザーにフィードバックが与えられます。 2、および3。

その後、注文はメッセージ通知サービスを通じて非同期に発注されます。手順 4 の非同期発注が失敗した場合は、操作が再試行され、注文が再生成されます。MQ メッセージも追跡できます。戻る。


オーダーが作成されるとキュー状態になり、サービスはイベント
Order Created をメッセージ キューに発行します。 つまり、注文サービスはメッセージを外部に送信します。注文を作成すると、その注文が MQ によってメッセージをサブスクライブするサービスに転送されます。

製品サービスが注文作成メッセージを受信すると、在庫控除操作が実行されます。在庫控除は不可抗力の要因により失敗する可能性があることに注意してください。成功または失敗に関係なく、製品サービスは在庫控除メッセージを MQ に送信し、メッセージの内容が在庫控除の結果となります。

注文サービスは在庫控除の結果をサブスクライブします。メッセージを受信した後:

    在庫控除が成功すると、注文ステータスが
  • 確認済みに変更されます。成功
  • 在庫控除が失敗した場合は、注文のステータスを
  • キャンセル済み、つまり注文が失敗した
  • に変更します。
上記のモデル要件を達成するには、信頼できる情報が必要です。サービスによって送信されたメッセージは、必ず MQ によって受信されます。

    ユーザー エクスペリエンスの変更
  • フロントエンドはキューイング メディア インターフェイスと連携します。
商品/注文サービスは非同期になっており、フラッシュセールのシナリオには適していますが、トラフィックが大きくない場合にはあまり適していません。

非同期設計

    在庫は Redis に保存されます
  1. リクエストを受信した後、Redis は在庫が十分であるかどうかを判断し、在庫を減算します。 Redis では
  2. 注文サービスは注文を作成してデータベースに書き込み、メッセージを送信します
  3. #注文の支払いが成功すると、アウトバウンド プロセスが発生します。このプロセスでは、送信配信が失敗する可能性があります。
インベントリには 2 つの部分があります:


キャッシュ redis レイヤー
  • データベース mysql レイヤー
カスタマー サービスが 5 つの新しいインベントリを追加すると、次に、キャッシュ Redis レイヤーとデータベース mysql レイヤーの両方で 5 つのインベントリーを追加する必要があり、分散トランザクションの最終整合性を使用して要件を満たす必要があります。すべてのインベントリーが追加されるか、何も追加されないかのいずれかです。
  1. 注文が生成されると、在庫を差し引く必要があります。
  2. 最初に Redis 在庫を差し引きます
  3. 。差し引きが成功すると、支払いのための注文が生成されます。このプロセス は、 mysql インベントリを差し引かないでください。 redis 在庫が差し引かれると、製品を注文できなくなり、注文が失敗するため、外側の層がブロックされます。
  4. ステップ 2
  5. Redis 在庫を正常に差し引いた後、
  6. 注文を生成し、支払いを行い、支払いが成功したら注文センターに戻ると、アウトバウンドがあることがわかります。プロセス。
  7. アウトバウンドプロセス
  8. MQ非同期的に分離されたタスクキュー、このプロセスはmysqlインベントリの控除
    :
mysql 在庫の減算が成功し、出荷が成功すると、注文プロセス全体が完了し、配送ステータスが入力されます。
  • mysql 在庫の減算が失敗し、出荷が失敗した場合、一連の操作が行われます。実行されました
  • 注文ステータスがキャンセルに変更されました
    • Redis インベントリを返品
    • 返金
  • ##Redis インベントリとmysql インベントリ

支払い前は 源泉徴収

、それは

redis インベントリの控除 、つまり在庫をロックするプロセスです 支払い後は、実際の控除、mysql インベントリーの控除 、インベントリーが最終的に一貫性があることを確認してください
ただし、極端な場合にはデータの不整合が発生する可能性があります

If redis inventory = mysql の在庫では問題ありません。

    If redis の在庫< ; mysql の在庫では、売られすぎの問題は発生しませんが、実際の在庫はあるのに売れないという状況が発生します。 redis インベントリ > mysql インベントリの場合、売られすぎ、売れすぎた注文は倉庫から出荷されます。プロセス中に失敗します。
  • この方法では、全体的に問題は発生せず、mysql データベースは最終的に在庫に問題がないことを保証します。 #########質問######

    データベース インベントリと Redis インベントリに一貫性がありません。それを検出するにはどうすればよいですか?

    不一致が検出された場合の同期方法

    良い計画が思いつきません
    もっと乱暴な方法は、午前1時などの低ピーク時間帯、定期的な強制取材。ただし、極端な場合には、同期後も不正確さが残る可能性があります。たとえば、同期プロセス中に、たまたま注文の支払いが発生しました。注文が正常に支払われた後、MySQL 在庫はアウトバウンド プロセス中に差し引かれますが、 Redis インベントリは差し引かれません。

    これはデータベース同期キャッシュの更新メカニズムに問題があります
    これは一貫した論理設計の問題です
    キャッシュ番号 = データベース インベントリ番号 - 番号差し引かれます
    もちろん、他の解決策もあり、一貫性の要件を考慮すると、単純な解決策も複雑な解決策も使用できます
    システムの複雑さに依存します。システムが大規模になるほど、より詳細な情報が必要になります。細分化する必要があります
    たとえば、差し引かれる数値をキューまたはキャッシュに置くことができ、同時にカウントもあります。カウントを直接読み取るだけです。
    たとえば、それが配置された場合モンゴでは、支払われて出荷される数量は一般にそれほど多くありません。数えるだけで大​​丈夫です。それほど多くは失われません。
    したがって、一般的なシステムでは、データ チェーンが確実に機能することを完全に保証することはできません。エラーは発生しませんが、補償が必要です。つまり、エラーは修正できます。
    エラーがないことを保証するコストは明らかに高すぎます。
    一連の同期が存在します。リフレッシュ メカニズムはスケジュール設定できます。 MQ を介して行うことも、同期との不整合を監視することもできます。 。 。
    キャッシュされたデータの鮮度の確保とも呼ばれます
    一般的には、30 分か数分程度で完了します。シナリオが異なればニーズも異なります

    12306

    12306 電車の切符を購入する場合、夜間は切符を購入できません。これはおそらく在庫を同期し、データベースの在庫を Redis インベントリーに同期させるためです。ただし、電車の切符を購入する場合は、実際の金額を差し引く必要があります。注文が生成される前に、在庫、つまり、mysql の在庫を差し引く必要があります。

    鉄道の切符を買うのは、ショッピングとは異なります。ショッピングは支払い後に倉庫から発送できますが、チケットを購入するのは、決済前にチケットを倉庫から発送する必要があるため、在庫から発送する在庫を差し引く必要がある 倉庫処理が進められ、倉庫の発送が成功して初めて注文が生成される Redis在庫の導入も必要.

    キャッシュ内のインベントリを最初に差し引く必要があります。差し引きが成功した後、mysql 内のインベントリを差し引くことができます。

    キャッシュ内のインベントリが差し引かれなかった場合、キャッシュはブロックされ、不十分なインベントリが返されます。これらのリクエストは mysql にパンクチャされず、リクエストの圧力のほとんどがブロックされます。

    Redis インベントリは、mysql インベントリと不一致になります。極端な場合には、いくつかの不一致があるはずであり、インベントリの同期が必要です。

    • キャッシュ在庫がデータベース在庫より多い場合 多すぎると、クエリにはチケットがあるように見えますが、注文することができず、注文すると在庫が足りないと言われます。この場合、データベースに過剰な負荷がかかりますが、12306 にはこの問題を回避する別の手段があるはずですが、実際に、チェックしたときにチケットがあったのに注文できないという状況に遭遇しました。

    • キャッシュ在庫がデータベース キャッシュより少ない場合は問題ありません。チケットのみが存在し、販売はありません。在庫の同期が完了すると、再び正確になります。明日。

以上がRedis での売れすぎ在庫の問題の解決の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。