巧用CAS解決資料併發一致性問題

2021-08-08 12:32:34 字數 2382 閱讀 2065

緣起

:在高併發的分布式環境下,對於資料的查詢與修改容易引發一致性問題,本文將分享一種非常簡單但有效的優化方法。

一、業務場景

業務場景為,購買商品的過程要對餘額進行查詢與修改,大致的業務流程如下:

(1)從資料庫查詢使用者現有餘額

select money from t_yue where uid=$uid,不妨設查詢出來的$old_money=100元

(2)業務層實施業務邏輯,比如購買乙個80元的商品,並且打九折

(3)將資料庫中的餘額進行修改

在併發量低的情況下,這個流程沒有任何問題,原有金額100元,購買了80元的九折商品(72元),剩餘28元。

二、潛在的問題

在分布式環境中,如果併發量很大,這種「查詢

+修改」的業務很容易出現資料不一致

。極限情況下,可能出現這樣的異常流程:

(1)業務1和業務2同時查詢餘額,是100元

(2)業務1和業務2進行邏輯計算,算出各自業務的餘額,假設業務1算出的餘額是28元,業務2算出的餘額是38元

(3)業務1對資料庫中的餘額先進行修改,設定成28元。

業務2對資料庫中的餘額後進行修改,設定成38元。

此時異常出現了,原有金額

100元,業務

1扣除了

72元,業務

2扣除了

62元,最後剩餘

38元。

三、問題原因

高併發環境下,對同乙個資料的併發讀(兩邊都讀出餘額是100)與併發寫(乙個寫回28,乙個寫回38)導致的資料一致性問題。

四、原因分析

業務1的寫回:原有金額100,這是乙個初始狀態,寫回金額28,理論上只有在原有金額為100的時候才允許寫回成功,這一步沒問題。

業務2的寫回:的原有金額100,這是乙個初始狀態,寫回金額38,理論上只有在原有金額為100的時候才允許寫回成功,可實際上,這個時候資料庫中的金額已經變為28了,這一步的寫操作不應該成功。

五、簡易解決方案

在set寫回的時候,加上初始狀態的條件compare,只有初始狀態不變時,才允許set寫回成功

,這正是大家常說的「compare and set」(cas),是一種常見的降低讀寫鎖衝突,保證資料一致性的方法。

六、業務的公升級

業務線使用cas解決高併發時資料一致性問題,

只需要在進行set操作時,compare一下初始值,如果初始值變換,不允許set成功。

對於上文中的業務場景,只需要將「updatet_yue set money=$new_money where uid=$uid」公升級為

「update t_yue setmoney-=$money where uid=$uid and money=$old_money

」即可。

併發操作發生時:

業務1執行 => update t_yue set money-=72

where uid=$uid and money=100

業務2執行 => update t_yue set money-=62

where uid=$uid and money=100

【這兩個操作同時進行時,只能有乙個執行成功】。

七、怎麼判斷哪個執行成功,哪個執行失敗

set操作,其實無所謂成功或者失敗,業務能通過affect rows得知哪個修改沒有成功:

執行成功的業務,affect rows為1

執行失敗的業務,affect rows為0

八、總結

高併發「查詢並修改」的場景,可以用cas(compare and set)的方式解決資料一致性問題。對應到業務,即

在set的時候,加上初始條件的比對

併發一致性解決方法

在sql中,當對資料庫中的乙個表進行併發操作時,會出現 資料丟失 不可重複讀 髒讀和幻影讀的情況。處理該併發問題的解決方法 1 封鎖 1.1 共享鎖 又稱讀鎖,如果事務a1用共享鎖讀取資料b,a1事務沒有結束,那麼事務a2在a1事務期間,可以 用共享 鎖來讀取資料,但不能用排它鎖來修改資料。1.2 ...

強一致性 弱一致性 最終一致性

這種方式在es等分布式系統中也有體現,可以設定主shard提交即返回成功,或者需要replica shard提交成功再返回。提到分布式架構就一定繞不開 一致性 問題,而 一致性 其實又包含了資料一致性和事務一致性兩種情況,本文主要討論資料一致性 事務一致性指acid 複製是導致出現資料一致性問題的唯...

CAS解決資料一致性問題

什麼是cas?compare and set cas 是一種常見的降低讀寫鎖衝突,保證資料一致性的方法。資料一致性是我們開發時必須注意的問題,特別涉及到錢這塊。這裡舉乙個使用者購物的例子 現有乙個使用者資訊表user account,表中字段為id,uid,amount。表中現有使用者甲,餘額100...