高并发场景下的难题及CAS方案
2024-10-10 09:53:44 作者:佚名
典型支付场景
这是最经典的场景。支付过程,要先查询买家的账户余额,然后计算商品价格,最后对买家进行进行扣款。在高并发的分布式业务场景中,类似这种 “查询+修改” 的操作很可能导致数据的不一致性。
在线下单场景
同理,买家在电商平台下单,往往会涉及到两个动作,一个是扣库存,第二个是更新订单状态,库存和订单一般属于不同的数据库,需要使用分布式事务保证数据一致性。
跨行转账场景
跨行转账问题也是一个典型的分布式事务,用户A向B的账户转账,要先进行A的账户-500,然后B的账户+500。为了保证这两个操作步骤的一致,数据一致性方案必然要被引入。
CAS方案
分布式CAS(Compare-and-Swap)模式是一种无锁化思想的应用,通过无锁算法实现线程间对共享资源的无冲突访问,既保证性能高效,有保证数据的强一致性,避免了一致性问题的产生。CAS模式包含三个基本操作数:内存地址V、旧的预期值A和要修改的新值B。在更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。
引出ABA问题
在CAS(Compare-and-Swap)操作中,ABA问题是一个常见的挑战。ABA问题是指当某个线程读取一个共享变量V的值为A,之后准备将其更新为B时,另一个线程可能已经将其从A改为了B,然后又改回了A。这可能导致数据一致性受损,并导致业务逻辑错误,难以调试与定位。
不同维度的处理方式
ABA出现的原因,是CAS的过程中,只关注Value值的校验,忽略了这个值还是不是之前的那个值。解决方案是给Value设置一个Version(版本号),用来比对,一个数据一个版本,每次数据变化的时候版本跟随变化,这样的话就不会随随便便修改成功。
应用程序层
Java中的java.util.concurrent.atomic包提供了解决ABA问题的工具类。在Go语言中,通常使用sync/atomic包提供的原子操作来处理并发问题,并引入版本号或时间戳的概念。
数据层
- CAS策略
- CAS策略+Version,避免ABA问题
update stock set num_val=$num_new_val where sid=$sid and num_val=$num_old_val
update stock set num=$num_new_val, version=$version_new where sid=$sid and version=$version_old
总结
- 高并发下的难题:支付、下单、跨行转账
- CAS方案以及引发的ABA问题
- 不同维度的处理方式:应用层、数据层