并发控制:确保数据一致性的策略

引言

​ 在现代软件开发中,尤其是在涉及高并发场景的应用,如在线购物、金融交易等,保证数据操作的原子性和一致性是至关重要的。本文将深入探讨并发环境下常见的问题,以及如何通过先进的技术手段确保数据的准确性和安全性。

案例分析:库存扣减的并发挑战
背景设定

​ 设想一个在线电商平台,其后端数据库中有一个名为 stock 的库存数据表,其中 stock_num 字段记录了商品的库存数量。

并发扣减库存的问题

​ 在高流量的购物节期间,库存扣减操作变得尤为关键。一个典型的扣减操作可能是执行如下 SQL 语句:

UPDATE stock SET stock_num = stock_num - 1 WHERE product_id = X;

以上操作会产生什么问题?

​ **不幂等:**当上次语句重复执行的时候会导致多次扣减库存,为什么会重复执行,比如业务侧重试、数据库代理重试等,因此我们可以先查出库存数量,得出新库存等于 new_stock = stock_num - 1, 最终语句如下:

update stock set stock_num = new_stock

​ **超卖:**并发场景解决了不幂等问题之后依然存在超卖问题,假如库存剩余1,两个并发请求同时查询库存为1,此时 new_stock_num = 1-1 ,两个请求同时执行 update stock set stock_num = new_stock_num,只有一个库存却卖出两件

怎么解决超卖问题

CAS(Compare-And-Swap) 机制的应用:我们在语句后面加上库存数量判断即可 ,然后根据 affetc row 0或1判断执行有没有成功,语句如下:

 update stock set stock_num  = new_stock_num where stock_num = old_stock_num

解决以上问题就万事大吉了吗,其实以上写法还有可能存在经典 ABA 问题

深入探讨:ABA 问题的识别与解决

​ 尽管 CAS 机制可以解决不幂等性和超卖问题,但它本身也有局限性,即所谓的 ABA 问题。ABA 问题描述了在并发编程中,一个值从 A 变为 B,再变回 A,而 CAS 操作却可能错误地认为值未发生变化。

举例解释:

  1. 张三去银行取钱,余额有 200 元,张三取 100 元,但因为程序的问题,启动了两个线程,线程一和线程二进行比对扣款,线程一获取原本有 200 元,扣除 100 元,余额等于 100 元 - 此时余额是100

  2. 李四给张三转账 100 元,于是启动了线程三抢先在线程二之前执行了转账操作,把 100 元又变成了 200 元 - 经过转账又变成了200

  3. 此时线程二对比自己事先拿到的 200 元和此时经过改动的 200 元值一样,就进行了减法操作,把余额又变成了 100 元 - 线程2是步骤一异常启动的线程,我们期望线程2不应该扣款但由于执行语句的判断条件是 old_money=200, 由于 ABA 问题导致条件判断成功,导致多扣了100

解决方案:引入版本号

​ ABA 问题的核心原因是因为被更新的变量会有加减操作,所以导致值会在新老数值之间变动,如果值只加不减,那么判断条件是不是就可以成立了,所以我们可以引入一个版本号字段 version,此时更新语句变成:

update stock set stock_num  = new_stock_num, version = new_version where stock_num = old_stock_num and version = old_version
Reference
  1. 深入理解 CAS 和 ABA 问题
  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值