庫存扣多了,到底怎麼辦
阿新 • • 發佈:2018-12-12
業務複雜、資料量大、併發量大的業務場景下,典型的網際網路架構,一般會分為這麼幾層:
呼叫層,一般是處於端上的瀏覽器或者App;
站點層,一般是拼裝html或者json返回的web-server層;
伺服器,一般是提供RPC呼叫介面的service層;
資料層,提供固化資料儲存的db
對於庫存業務,一般有個庫存服務(stock-service
)提供庫存的查詢get stock、扣減reduce stock、設定set stock
等RPC介面。
庫存查詢,stock-service本質上執行的是:
select num from stock where id=$id;
庫存扣減,stock-service本質上執行的是:
update stock set num = num - $reduce where id=$id;
庫存設定,stock-service本質上執行的是:
update stock set num = $new_num where id=$id;
使用者下單前,一般會對庫存進行查詢,有足夠的存量才允許扣減。
但是在併發量很大的情況下,會有問題:比如2個併發操作,查詢庫存,得到的值都是5。接下來使用者發生了併發的購買動作(秒殺類業務特別容易出現): 使用者1購買了3個,於是庫存修改為2; 使用者2購買了2個,於是庫存要修改為3。
這2個修改庫存的介面併發執行,庫存會先變成2,再變成3,導致資料不一致
其根本原因是,修改庫存操作發生的時候,沒有檢查庫存和查詢出來的庫存有沒有變化。 升級庫存設定介面也很容易:
update stock set num = $new_new where id=$id and num = $old_num;
這就是大家常說的Compare And Set(CAS)
,是一種常見的降低讀寫鎖衝突、保證資料一致性的方法。