W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
業(yè)務(wù)場景為,購買商品的過程要對余額進(jìn)行查詢與修改,大致的業(yè)務(wù)流程如下:
(1)從數(shù)據(jù)庫查詢用戶現(xiàn)有余額 SELECT money FROM t_yue WHERE uid=$uid,不妨設(shè)查詢出來的$old_money=100元
(2)業(yè)務(wù)層實(shí)施業(yè)務(wù)邏輯,比如購買一個(gè)80元的商品,并且打九折
if($old_money> 80*0.9) $new_money=$old_money-80*0.9=28
在分布式環(huán)境中,如果并發(fā)量很大,這種“查詢+修改”的業(yè)務(wù)很容易出現(xiàn)數(shù)據(jù)不一致。極限情況下,可能出現(xiàn)這樣的異常流程:
(1)業(yè)務(wù)1和業(yè)務(wù)2同時(shí)查詢余額,是100元
(3)業(yè)務(wù)1對數(shù)據(jù)庫中的余額先進(jìn)行修改,設(shè)置成28元。
業(yè)務(wù)2對數(shù)據(jù)庫中的余額后進(jìn)行修改,設(shè)置成38元。
高并發(fā)環(huán)境下,對同一個(gè)數(shù)據(jù)的并發(fā)讀(兩邊都讀出余額是100)與并發(fā)寫(一個(gè)寫回28,一個(gè)寫回38)導(dǎo)致的數(shù)據(jù)一致性問題。
業(yè)務(wù)1的寫回:原有金額100,這是一個(gè)初始狀態(tài),寫回金額28,理論上只有在原有金額為100的時(shí)候才允許寫回成功,這一步?jīng)]問題。
業(yè)務(wù)2的寫回:的原有金額100,這是一個(gè)初始狀態(tài),寫回金額38,理論上只有在原有金額為100的時(shí)候才允許寫回成功,可實(shí)際上,這個(gè)時(shí)候數(shù)據(jù)庫中的金額已經(jīng)變?yōu)?8了,這一步的寫操作不應(yīng)該成功。
在set寫回的時(shí)候,加上初始狀態(tài)的條件compare,只有初始狀態(tài)不變時(shí),才允許set寫回成功,這正是大家常說的“Compare And Set”(CAS),是一種常見的降低讀寫鎖沖突,保證數(shù)據(jù)一致性的方法。
業(yè)務(wù)線使用CAS解決高并發(fā)時(shí)數(shù)據(jù)一致性問題,只需要在進(jìn)行set操作時(shí),compare一下初始值,如果初始值變換,不允許set成功。
對于上文中的業(yè)務(wù)場景,只需要將“UPDAtEt_yue SET money=$new_money WHERE uid=$uid”升級為
“UPDAtE t_yue SETmoney=$new_money WHERE uid=$uid AND money=$old_money”即可。
并發(fā)操作發(fā)生時(shí):
業(yè)務(wù)1執(zhí)行 => UPDAtE t_yue SET money=28 WHERE uid=$uid AND money=100業(yè)務(wù)2執(zhí)行 => UPDAtE t_yue SET money=38 WHERE uid=$uid AND money=100
【這兩個(gè)操作同時(shí)進(jìn)行時(shí),只能有一個(gè)執(zhí)行成功】。
set操作,其實(shí)無所謂成功或者失敗,業(yè)務(wù)能通過affect rows得知哪個(gè)修改沒有成功:
執(zhí)行成功的業(yè)務(wù),affect rows為1
執(zhí)行失敗的業(yè)務(wù),affect rows為0
高并發(fā)“查詢并修改”的場景,可以用CAS(Compare and Set)的方式解決數(shù)據(jù)一致性問題。對應(yīng)到業(yè)務(wù),即在set的時(shí)候,加上初始條件的比對。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: