CAS下ABA问题及优化方案(1)

三、CAS优化

大家常说的“Compare And Set”(CAS),是一种常见的降低读写锁冲突,保证数据一致性的乐观锁机制。

针对上述库存扣减的例子,CAS升级很容易,将库存设置接口执行的SQL:

update stock set num= n u m _ n e w w h e r e s i d = num\_new where sid= num_newwheresid=sid

升级为:

update stock set num= n u m _ n e w w h e r e s i d = num\_new where sid= num_newwheresid=sid and num=$num_old

即可。

四、什么是ABA问题

CAS乐观锁机制确实能够提升吞吐,并保证一致性,但在极端情况下可能会出现ABA问题。

什么是ABA问题?

考虑如下操作:

  • 并发1(上):获取出数据的初始值是A,后续计划实施CAS乐观锁,期望数据仍是A的时候,修改才能成功

  • 并发2:将数据修改成B

  • 并发3:将数据修改回A

  • 并发1(下):CAS乐观锁,检测发现初始值还是A,进行数据修改

上述并发环境下,并发1在修改数据时,虽然还是A,但已经不是初始条件的A了,中间发生了A变B,B又变A的变化,此A已经非彼A,数据却成功修改,可能导致错误,这就是CAS引发的所谓的ABA问题。

库存操作,出现ABA问题并不会对业务产生影响。

再看一个堆栈操作的例子:

CAS下ABA问题及优化方案|架构师之路

并发1(上):读取栈顶的元素为“A1”

CAS下ABA问题及优化方案|架构师之路

并发2:进行了2次出栈

CAS下ABA问题及优化方案|架构师之路

并发3:又进行了1次出栈

CAS下ABA问题及优化方案|架构师之路

并发1(下):实施CAS乐观锁,发现栈顶还是“A1”,于是修改为A2

CAS下ABA问题及优化方案|架构师之路

此时会出现系统错误,因为此“A1”非彼“A1”

五、ABA问题的优化

ABA问题导致的原因,是CAS过程中只简单进行了“值”的校验,再有些情况下,“值”相同不会引入错误的业务逻辑(例如库存),有些情况下,“值”虽然相同,却已经不是原来的数据了。

优化方向:CAS不能只比对“值”,还必须确保的是原来的数据,才能修改成功。

常见实践:“版本号”的比对,一个数据一个版本,版本变化,即使值相同,也不应该修改成功。

库存的并发读写例子,引入版本号的具体实践如下:

(1)库存表由

stock(sid, num)

升级为

stock(sid, num, version)

(2)查询库存时同时查询版本号

select num from stock where sid=$sid

升级为

select num, version from stock where sid=$sid

CAS下ABA问题及优化方案|架构师之路

假设有并发操作,都会将版本号查询出来

(3)设置库存时,必须版本号相同,并且版本号要修改

旧版本**“值”比对**CAS

update stock set num= n u m _ n e w w h e r e s i d = num\_new where sid= num_newwheresid=sid and num=$num_old

升级为**“版本号”比对**CAS

update stock set num= n u m _ n e w ,   ∗ ∗ v e r s i o n = num\_new, **version= num_new, version=version_new**

where sid= s i d a n d   ∗ ∗ v e r s i o n = sid and **version= sidand version=version_old**

CAS下ABA问题及优化方案|架构师之路

此时假设有并发操作,第一个操作,比对版本号成功,于是把库存和版本号都进行了修改。

  • 20
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值