電子商取引のシーン:同時に在庫を差し引いて、どのように超過販売しないでまた同時性能に影響しないことを保証します
2217 ワード
パンゴがやってきました2019-09-22 13:03:27
どの電子商取引プラットフォームの主なビジネスシーンは次のとおりです.はショッピングカートに加入した. 決算に行って、受取住所を記入/選択する. 在庫を検査/控除し、注文を生成し、支払いを行う.
ここで、第3のステップでは、在庫の検査/控除を行い、通常のコードは以下のように実現されます.
残りの在庫量を判断し、在庫が十分であれば、控除操作を行う.
一般的に、1枚の注文で1つの商品だけを買うことはありませんが、複数ある場合は、上記を繰り返す必要があります.
この方式の最大の問題は同時をサポートしないことであり、同時数が2つであっても、在庫控除エラーが発生する可能性がある.
残りの在庫を取得するのは実際のupdateと時間差があるため、この時2つの注文要求があると仮定し、いずれもa 1を購入し、この時の残りの在庫は1であり、この2つの注文要求は同時にselect要求が残りの1つの在庫に達し、いずれも順調に後続の操作を実行することができ、最終的には2つを販売し、超過販売をもたらす.
この問題を解決するには、最も簡単な方法はトランザクションに参加することですが、トランザクションはロックテーブル、ロックローをもたらし、効率が低下します.
1つの解決策:updateの場合、条件を追加します.
より直接的な方法は、残りの在庫を先に照会する必要がなく、直接update
updateは同時シリアルで実行され、高くて発行され、在庫が不足した場合、実行に失敗します.
今、このようなシーンを想定して、1万人のユーザーが、N種類の商品を買い占め、各商品の在庫は100件です.各ユーザーは同時にn種類の商品を買い占める可能性がある.
実際の経験から推定すると、3万人以下のユーザーはmysqlのupdateメカニズムを利用して、十分に対応して、ここではより大きな同時の状況を考慮しないで、より大きな同時のシーンはredisなどの解決策を導入する必要があります.
トランザクションの効率が悪いことを考慮して、ここではトランザクションを捨てて、在庫控除の失敗したロールバックを実現するためにキューを導入します.
説明:ユーザー数!=同時購入数は、一般的には1分目に集中することが多く、高合併では500 msを超えるインタフェースが現れず、システムが正常に動作し、ユーザー体験が合格し、ユーザーは基本的に30秒以内に商品を閲覧し、ショッピングカートに参加し、注文する操作を完了することができると考えられている.
以上のシナリオではredisを導入しない場合,mysqlのロックメカニズムのみを利用して3万人のユーザの1分間の高アクセスを受け,6万-10万人のシングルを生成することは可能である.
同時シーンの要求がより高い場合、mysqlマルチプライマリマルチスレーブ、redis/zkなどを導入することができる.
どの電子商取引プラットフォームの主なビジネスシーンは次のとおりです.
ここで、第3のステップでは、在庫の検査/控除を行い、通常のコードは以下のように実現されます.
残りの在庫量を判断し、在庫が十分であれば、控除操作を行う.
select stock from goods_stock where sku = 'a1'
if(stock - buy_num) >= 0){ //
stock = stock - buy_num;
update goods_stock set stock = stock where sku = 'a1'
}
一般的に、1枚の注文で1つの商品だけを買うことはありませんが、複数ある場合は、上記を繰り返す必要があります.
この方式の最大の問題は同時をサポートしないことであり、同時数が2つであっても、在庫控除エラーが発生する可能性がある.
残りの在庫を取得するのは実際のupdateと時間差があるため、この時2つの注文要求があると仮定し、いずれもa 1を購入し、この時の残りの在庫は1であり、この2つの注文要求は同時にselect要求が残りの1つの在庫に達し、いずれも順調に後続の操作を実行することができ、最終的には2つを販売し、超過販売をもたらす.
この問題を解決するには、最も簡単な方法はトランザクションに参加することですが、トランザクションはロックテーブル、ロックローをもたらし、効率が低下します.
1つの解決策:updateの場合、条件を追加します.
update goods_stock set stock = stock where sku = 'a1' and stock = old_stock
より直接的な方法は、残りの在庫を先に照会する必要がなく、直接update
update goods_stock set stock = stock - buy_num where sku = 'a1' and (stock-buy_num) >= 0 ;
updateは同時シリアルで実行され、高くて発行され、在庫が不足した場合、実行に失敗します.
今、このようなシーンを想定して、1万人のユーザーが、N種類の商品を買い占め、各商品の在庫は100件です.各ユーザーは同時にn種類の商品を買い占める可能性がある.
実際の経験から推定すると、3万人以下のユーザーはmysqlのupdateメカニズムを利用して、十分に対応して、ここではより大きな同時の状況を考慮しないで、より大きな同時のシーンはredisなどの解決策を導入する必要があります.
トランザクションの効率が悪いことを考慮して、ここではトランザクションを捨てて、在庫控除の失敗したロールバックを実現するためにキューを導入します.
boolean isSuccess = true;
for (sku in goods){
if(update goods_stock set stock = stock - sku[num] where sku = sku[sn] and (stock-sku[num]) >= 0 ){
sku_success[] = {sku[sn],sku[num]}
}else{
//
push_queue(sku_success[]) // , ;
isSuccess = false;
}
}
if (isSuccess){
//
createOrder();
}else{
// : , ;
}
説明:ユーザー数!=同時購入数は、一般的には1分目に集中することが多く、高合併では500 msを超えるインタフェースが現れず、システムが正常に動作し、ユーザー体験が合格し、ユーザーは基本的に30秒以内に商品を閲覧し、ショッピングカートに参加し、注文する操作を完了することができると考えられている.
以上のシナリオではredisを導入しない場合,mysqlのロックメカニズムのみを利用して3万人のユーザの1分間の高アクセスを受け,6万-10万人のシングルを生成することは可能である.
同時シーンの要求がより高い場合、mysqlマルチプライマリマルチスレーブ、redis/zkなどを導入することができる.