自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

并發(fā)扣款一致性優(yōu)化,CAS下ABA問(wèn)題,這個(gè)話題還沒(méi)聊完!?。?/h1>

開(kāi)發(fā) 開(kāi)發(fā)工具 前端
上一篇答星球水友提問(wèn),《并發(fā)扣款,如何保證數(shù)據(jù)的一致性?》中提到:用CAS樂(lè)觀鎖,可以在盡量不影響吞吐量的情況下,保證數(shù)據(jù)的一致性。

上一篇答星球水友提問(wèn),《并發(fā)扣款,如何保證數(shù)據(jù)的一致性?》中提到:用CAS樂(lè)觀鎖,可以在盡量不影響吞吐量的情況下,保證數(shù)據(jù)的一致性。

[[275951]]

大家有非常多的留言,大概有這么幾類(lèi):

  • 是否存在ABA問(wèn)題?
  • 為什么不能用:
    1. UPDATE t_yue SET moneymoney=money-$diff AND money>=$diff; 
  • 能否借助redis事務(wù)來(lái)扣減余額;

畫(huà)外音:請(qǐng)務(wù)必閱讀前序文章:《并發(fā)扣款,如何保證數(shù)據(jù)的一致性?》。

問(wèn)題比較多,今天先聊第一個(gè)問(wèn)題,ABA。

什么是ABA問(wèn)題?

CAS樂(lè)觀鎖機(jī)制確實(shí)能夠提升吞吐,并保證一致性,但在極端情況下可能會(huì)出現(xiàn)ABA問(wèn)題。

考慮如下操作:

  • 并發(fā)1(上):獲取出數(shù)據(jù)的初始值是A,后續(xù)計(jì)劃實(shí)施CAS樂(lè)觀鎖,期望數(shù)據(jù)仍是A的時(shí)候,修改才能成功
  • 并發(fā)2:將數(shù)據(jù)修改成B
  • 并發(fā)3:將數(shù)據(jù)修改回A
  • 并發(fā)1(下):CAS樂(lè)觀鎖,檢測(cè)發(fā)現(xiàn)初始值還是A,進(jìn)行數(shù)據(jù)修改

上述并發(fā)環(huán)境下,并發(fā)1在修改數(shù)據(jù)時(shí),雖然還是A,但已經(jīng)不是初始條件的A了,中間發(fā)生了A變B,B又變A的變化,此A已經(jīng)非彼A,數(shù)據(jù)卻成功修改,可能導(dǎo)致錯(cuò)誤,這就是CAS引發(fā)的所謂的ABA問(wèn)題。

余額操作,出現(xiàn)ABA問(wèn)題并不會(huì)對(duì)業(yè)務(wù)產(chǎn)生影響,因?yàn)閷?duì)于“余額”屬性來(lái)說(shuō),前一個(gè)A為100余額,與后一個(gè)A為100余額,本質(zhì)是相同的。

但其他場(chǎng)景未必是這樣,舉一個(gè)堆棧操作的例子:

并發(fā)1(上):讀取棧頂?shù)脑貫?ldquo;A1”

并發(fā)2:進(jìn)行了2次出棧

并發(fā)3:又進(jìn)行了1次出棧

并發(fā)1(下):實(shí)施CAS樂(lè)觀鎖,發(fā)現(xiàn)棧頂還是“A1”,于是修改為A2

此時(shí)會(huì)出現(xiàn)系統(tǒng)錯(cuò)誤,因?yàn)榇?ldquo;A1”非彼“A1”

ABA問(wèn)題可以怎么優(yōu)化?

ABA問(wèn)題導(dǎo)致的原因,是CAS過(guò)程中只簡(jiǎn)單進(jìn)行了“值”的校驗(yàn),再有些情況下,“值”相同不會(huì)引入錯(cuò)誤的業(yè)務(wù)邏輯(例如余額),有些情況下,“值”雖然相同,卻已經(jīng)不是原來(lái)的數(shù)據(jù)了(例如堆棧)。

因此,CAS不能只比對(duì)“值”,還必須確保是原來(lái)的數(shù)據(jù),才能修改成功。

常見(jiàn)的實(shí)踐是,將“值”比對(duì),升級(jí)為“版本號(hào)”的比對(duì),一個(gè)數(shù)據(jù)一個(gè)版本,版本變化,即使值相同,也不應(yīng)該修改成功。

余額并發(fā)讀寫(xiě)例子,引入版本號(hào)的具體實(shí)踐如下:

(1)余額表要升級(jí)。

  1. t_yue(uid, money) 

升級(jí)為:

  1. t_yue(uid, money, version) 

(2)查詢余額時(shí),同時(shí)查詢版本號(hào)。

  1. SELECT money FROM t_yue WHERE sid=$sid 

升級(jí)為:

  1. SELECT money,version FROM t_yue WHERE sid=$sid 

假設(shè)有并發(fā)操作,都會(huì)將版本號(hào)查詢出來(lái)。

(3)設(shè)置余額時(shí),必須版本號(hào)相同,并且版本號(hào)要修改。舊版本“值”比對(duì):

  1. UPDATE t_yue SET money=38 WHERE uid=$uid AND money=100 

升級(jí)為“版本號(hào)”比對(duì):

  1. UPDATE t_yue SET money=38version=$version_new WHERE uid=$uid AND version=$version_old 

 

此時(shí)假設(shè)有并發(fā)操作,首先操作的請(qǐng)求會(huì)修改版本號(hào),并發(fā)操作會(huì)執(zhí)行失敗。

畫(huà)外音:version通用,本例是強(qiáng)行用version舉例而已,實(shí)際上本例可以用余額“值”比對(duì)。

總結(jié)

  • select&set業(yè)務(wù)場(chǎng)景,在并發(fā)時(shí)會(huì)出現(xiàn)一致性問(wèn)題
  • 基于“值”的CAS樂(lè)觀鎖,可能導(dǎo)致ABA問(wèn)題
  • CAS樂(lè)觀鎖,必須保證修改時(shí)的“此數(shù)據(jù)”就是“彼數(shù)據(jù)”,應(yīng)該由“值”比對(duì),優(yōu)化為“版本號(hào)”比對(duì)

思路比結(jié)論重要。

【本文為51CTO專(zhuān)欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來(lái)源: 51CTO專(zhuān)欄
相關(guān)推薦

2019-09-08 22:45:48

并發(fā)扣款一致性冪等性

2022-10-19 12:22:53

并發(fā)扣款一致性

2019-08-30 12:46:10

并發(fā)扣款查詢SQL

2024-01-10 08:01:55

高并發(fā)場(chǎng)景悲觀鎖

2017-06-23 07:15:52

庫(kù)存ABACAS

2016-11-29 09:00:19

分布式數(shù)據(jù)一致性CAS

2017-07-02 16:28:06

MySQL數(shù)據(jù)庫(kù)集群

2017-07-25 14:38:56

數(shù)據(jù)庫(kù)一致性非鎖定讀一致性鎖定讀

2022-08-29 08:38:00

事務(wù)一致性

2022-12-14 08:23:30

2022-08-11 07:55:05

數(shù)據(jù)庫(kù)Mysql

2019-09-18 08:41:53

并發(fā)扣減一致性redis

2021-04-24 16:58:03

數(shù)據(jù)庫(kù)工具技術(shù)

2023-12-01 13:51:21

數(shù)據(jù)一致性數(shù)據(jù)庫(kù)

2021-02-05 08:00:48

哈希算法?機(jī)器

2019-03-27 13:56:39

緩存雪崩穿透

2021-02-02 12:40:50

哈希算法數(shù)據(jù)

2020-05-12 10:43:22

Redis緩存數(shù)據(jù)庫(kù)

2020-11-24 09:03:41

一致性MySQLMVCC

2022-03-22 09:54:22

Hash算法
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)