新聞中心
業(yè)務(wù)復(fù)雜、數(shù)據(jù)量大、并發(fā)量大的業(yè)務(wù)場(chǎng)景下,典型的互聯(lián)網(wǎng)架構(gòu),一般會(huì)分為這么幾層:

成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站建設(shè)、網(wǎng)站制作、左權(quán)網(wǎng)絡(luò)推廣、小程序開(kāi)發(fā)、左權(quán)網(wǎng)絡(luò)營(yíng)銷、左權(quán)企業(yè)策劃、左權(quán)品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供左權(quán)建站搭建服務(wù),24小時(shí)服務(wù)熱線:18982081108,官方網(wǎng)址:www.cdcxhl.com
- 調(diào)用層,一般是處于端上的browser或者APP
- 站點(diǎn)層,一般是拼裝html或者json返回的web-server層
- 服務(wù)層,一般是提供RPC調(diào)用接口的service層
- 數(shù)據(jù)層,提供固化數(shù)據(jù)存儲(chǔ)的db
對(duì)于庫(kù)存業(yè)務(wù),一般有個(gè)庫(kù)存服務(wù),提供庫(kù)存的查詢、扣減、設(shè)置等RPC接口:
- 庫(kù)存查詢,stock-service本質(zhì)上執(zhí)行的是
- select num from stock where sid=$sid
- 庫(kù)存扣減,stock-service本質(zhì)上執(zhí)行的是
- update stock set numnum=num-$reduce where sid=$sid
- update stock set num=$num_new where sid=$sid
用戶下單前,一般會(huì)對(duì)庫(kù)存進(jìn)行查詢,有足夠的存量才允許扣減:
如上圖所示,通過(guò)查詢接口,得到庫(kù)存是5。
用戶下單時(shí),接著會(huì)對(duì)庫(kù)存進(jìn)行扣減:
如上圖所示,購(gòu)買(mǎi)3單位的商品,通過(guò)扣減接口,最終得到庫(kù)存是2。
希望設(shè)計(jì)往往有容錯(cuò)機(jī)制,例如“重試”,如果通過(guò)扣減接口來(lái)修改庫(kù)存,在重試時(shí),可能會(huì)得到錯(cuò)誤的數(shù)據(jù),導(dǎo)致重復(fù)扣減:
如上圖所示,如果數(shù)據(jù)庫(kù)層面有重試容錯(cuò)機(jī)制,可能導(dǎo)致一次扣減執(zhí)行兩次,最終得到一個(gè)負(fù)數(shù)的錯(cuò)誤庫(kù)存。
重試導(dǎo)致錯(cuò)誤的根本原因,是因?yàn)椤翱蹨p”操作是一個(gè)非冪等的操作,不能夠重復(fù)執(zhí)行,改成設(shè)置操作則不會(huì)有這個(gè)問(wèn)題:
如上圖所示,同樣是購(gòu)買(mǎi)3單位的商品,通過(guò)設(shè)置庫(kù)存操作,即使有重試容錯(cuò)機(jī)制,也不會(huì)得到錯(cuò)誤的庫(kù)存,設(shè)置庫(kù)存是一個(gè)冪等操作。
在并發(fā)量很大的情況下,還會(huì)有其他的問(wèn)題:
如上圖所示,兩個(gè)并發(fā)的操作,查詢庫(kù)存,都得到了庫(kù)存是5。
接下來(lái)用戶發(fā)生了并發(fā)的購(gòu)買(mǎi)動(dòng)作(秒殺類業(yè)務(wù)特別容易出現(xiàn)):
如上圖所示:
- 用戶1購(gòu)買(mǎi)了3個(gè)庫(kù)存,于是庫(kù)存要設(shè)置為2
- 用戶2購(gòu)買(mǎi)了2個(gè)庫(kù)存,于是庫(kù)存要設(shè)置為3
- 這兩個(gè)設(shè)置庫(kù)存的接口并發(fā)執(zhí)行,庫(kù)存會(huì)先變成2,再變成3,導(dǎo)致數(shù)據(jù)不一致(實(shí)際賣(mài)出了5件商品,但庫(kù)存只扣減了2,***一次設(shè)置庫(kù)存會(huì)覆蓋和掩蓋前一次并發(fā)操作)
其根本原因是,設(shè)置操作發(fā)生的時(shí)候,沒(méi)有檢查庫(kù)存與查詢出來(lái)的庫(kù)存有沒(méi)有變化,理論上:
- 庫(kù)存為5時(shí),用戶1的庫(kù)存設(shè)置才能成功
- 庫(kù)存為5時(shí),用戶2的庫(kù)存設(shè)置才能成功
實(shí)際執(zhí)行的時(shí)候:
- 庫(kù)存為5,用戶1的set stock 2確實(shí)應(yīng)該成功
- 庫(kù)存變?yōu)?了,用戶2的set stock 3應(yīng)該失敗掉
升級(jí)修改很容易,將庫(kù)存設(shè)置接口,stock-service上執(zhí)行的:
- update stock set num=$y where sid=$sid
升級(jí)為:
- update stock set num=$num_new where sid=$sid and num=$num_old
這正是大家常說(shuō)的“Compare And Set”(CAS),是一種常見(jiàn)的降低讀寫(xiě)鎖沖突,保證數(shù)據(jù)一致性的方法。
總結(jié)
在業(yè)務(wù)復(fù)雜,數(shù)據(jù)量大,并發(fā)量大的情況下,庫(kù)存扣減容易引發(fā)數(shù)據(jù)的不一致,常見(jiàn)的優(yōu)化方案有兩個(gè):
- 調(diào)用“設(shè)置庫(kù)存”接口,能夠保證數(shù)據(jù)的冪等性
- 在實(shí)現(xiàn)“設(shè)置庫(kù)存”接口時(shí),需要加上原有庫(kù)存的比較,才允許設(shè)置成功,能解決高并發(fā)下庫(kù)存扣減的一致性問(wèn)題
【本文為專欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】
當(dāng)前題目:庫(kù)存扣多了,到底怎么整?
轉(zhuǎn)載源于:http://m.5511xx.com/article/dpdjcgd.html


咨詢
建站咨詢
