高并发下如何保证数据的一致性

拿转账来说,在高并发下场景下,对账户余额操作的一致性,是非常重要的。如果代码写的时候没考虑并发一致性,就会导致公司亏损。所以本篇主要聊一下,如何在并发场景下,保证账户余额的一致性。

扣款流程

伪代码

public void transfer(Long id, Double payAmount){# 查询账户总额SELECT amount FROM account WHERE id=${id};#更新余额  UPDATE account SET amount=amount-payAmount WHERE id=${id};
}

以上流程如果并发量非常低的情况下是没问题的,但是如果在高并发下是很容易出现问题的。

在高并发下会出现什么问题?

假设 订单A 和 订单B 在同一时间都查询到了,账户余额为1000

订单A 扣款200,订单B 扣款 100,都满足1000-减去扣款金额大于0

执行扣款,订单A 修改账户余额为800,订单B 修改为账户余额为900

此时就出现问题了,如果 订单A 先执行更新,订单B 后执行,那么账户余额最终为900,反之为 800,都不正确,正确余额应该是700,那怎么处理呢?

并发扣款怎么处理?

使用悲观锁

在执行扣款时使用分布式锁或者数据库的 for update 对账户数据进行行级锁,使执行并发操作串型化操作。在这里使用 for update 做操作,这是数据库最简单的,但不推荐。

使用 for update 的方式,可能会带来很多问题,因为他是一个行级锁,高并发的情况下可能会导致死锁、客户端连接超时等问题。

如果一定要使用 for update,要注意 where 条件是唯一索引,否则会导致多行数据被锁,同时必须要开始事务,否则 for update 没效果,使用分布式数据库中间件还要注意,for update 可能会路由到读节点上。

使用乐观锁(CAS)

乐观锁的方式也就是是CAS的方式,适合并发量不高情况,如果并发量高大概率都失败在重试,开销也不比悲观锁小。

增加版本号方式

在查询余额时,加上版本号。

SELECT amount,version FROM account WHERE id=${id}

每次更新余额时,必须版本号相等,并且版本号每次要修改。

UPDATE account SET amount=余额,version=newVersion WHERE id=${id} AND version=${oldVersion}

使用原有金额值比对更新

在执行账户余额更新时,where 条件中增加第一次查出来的账户余额,即初始余额,如果在执行更新时,初始余额没变则更新成功,否则肯定是更新了,同时数据库也会返回受影响的行数,来判断是否更新成功,如果没成功就再次重试,同时还要考虑幂等性。

UPDATE account SET amount=余额 WHERE id=${id} AND amount=${oldAmount}

订单A 执行

UPDATE account SET amount=800 WHERE id=${id} AND amount=1000;

订单B 执行

UPDATE account SET amount=900 WHERE id=${id} AND amount=1000;

以上两笔执行只有一笔能成功,因为 amount 变了。

注意

在使用乐观锁时需要注意 ABA 的问题。拿上述场景举例:

订单A:获取出账户余额为 1000,期望余额是 1000 的时候,才能修改成功。

订单B:取了 100,将余额修改成了 900。

订单C:存进去了100,将余额修改成了 1000。

订单A:检查账户余额为 1000,进行扣款 200,账户余额变成了 800。

以上场景账户资金损失吗?没有,不过为了避免产生误解,推荐还是使用版本号的方式!

总结

在并发量高的情况下推荐使用悲观锁的方式,如果并发量不高可以考虑使用乐观锁,但是要注意幂等性,推荐使用版本号方式。同时乐观锁场景要注意 aba 的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2808256.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

常用实验室器皿耐硝酸盐酸进口PFA材质容量瓶螺纹盖密封效果好

PFA容量瓶规格参考:10ml、25ml、50ml、100ml、250ml、500ml、1000ml。 别名可溶性聚四氟乙烯容量瓶、特氟龙容量瓶。常用于ICP-MS、ICP-OES等痕量分析以及同位素分析等实验,也可在地质、电子化学品、半导体分析测试、疾控中心、制药厂、环境检测中心等机…

【Linux基础】vim、常用指令、组管理和组权限

Linux基础 1、目录结构2、vi和vim3、常用指令运行级别找回密码帮助指令时间日期指令搜索查找文件目录操作磁盘管理指令压缩和解压缩 4、组管理和组权限用户操作指令权限 1、目录结构 Linux的文件系统是采用级层式的树状目录结构,在此结构中的最上层是根目录“/”&a…

Repeater:创建大量类似项

Repeater 类型用于创建大量类似项。与其它视图类型一样,Repeater有一个model和一个delegate。 首次创建Repeater时,会创建其所有delegate项。若存在大量delegate项,并且并非所有项都必须同时可见,则可能会降低效率。 有2种方式可…

C语言第三十弹---自定义类型:结构体(上)

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】 结构体 1、结构体类型的声明 1.1、结构体回顾 1.1.1、结构的声明 1.1.2、结构体变量的创建和初始化 1.2、结构的特殊声明 1.3、结构的自引用 2、结构体内存…

未来已来:数字孪生与智慧园区的深度融合

目录 一、数字孪生技术的概述 二、智慧园区的概念和发展 三、数字孪生与智慧园区的深度融合 四、数字孪生与智慧园区的未来展望 五、结论 随着科技的飞速发展,我们正处在一个日新月异的时代。数字孪生技术作为新兴的前沿科技,已经引起了全球范围内的…

【人脸朝向识别与分类预测】基于PNN神经网络

课题名称:基于PNN神经网络的人脸朝向识别分类 版本日期:2024-02-20 运行方式:直接运行PNN0503.m文件 代码获取方式:私信博主或 QQ:491052175 模型描述: 采集到一组人脸朝向不同角度时的图像,图像来自不…

奇异递归模板模式应用6-类模板enable_shared_from_this

异步编程中存在一种场景,需要在类中将该类的对象注册到某个回调类或函数中,不能简单地将this传递给回调类中,很可能因为回调时该对象不存在而导致野指针访问(也有可能在析构函数解注册时被回调,造成对象不完整&#xf…

[VNCTF2024]-Web:CheckIn解析

查看网页 一款很经典的游戏,而且是用js写的 在调试器里面我们可以看见,如果游戏通关的话,它会进行一系列操作,包括使用console.log(_0x3d9d[0]);输出_0x3d9d[0]到控制台,那我们就直接在点击在控制台求出它的值

初始Nginx(基本概念)

目录 一、Nginx的概念 二、Nginx常用功能 1、HTTP(正向)代理,反向代理 1.1正向代理 1.2 反向代理 2、负载均衡 2.1 轮询法(默认方法) 2.2 weight权重模式(加权轮询) 2.3 ip_hash 3、web缓存 三、基础特性 四…

论文阅读:Ground-Fusion: A Low-cost Ground SLAM System Robust to Corner Cases

前言 最近看到一篇ICRA2024上的新文章,是关于多传感器融合SLAM的,好像使用了最近几年文章中较火的轮式里程计。感觉这篇文章成果不错,代码和数据集都是开源的,今天仔细读并且翻译一下,理解创新点、感悟研究方向、指导…

挑战杯 基于大数据的股票量化分析与股价预测系统

文章目录 0 前言1 课题背景2 实现效果3 设计原理QTChartsarma模型预测K-means聚类算法算法实现关键问题说明 4 部分核心代码5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于大数据的股票量化分析与股价预测系统 该项目较为新颖…

网络安全“三保一评”深度解析

“没有网络安全就没有国家安全”。近几年,我国法律法规陆续发布实施,为承载我国国计民生的重要网络信息系统的安全提供了法律保障,正在实施的“3保1评”为我国重要网络信息系统的安全构筑了四道防线。 什么是“3保1评”? 等保、分…

爬虫入门四(抽屉半自动点赞、xpath使用、动作链、打码平台、scrapy框架介绍与安装及创建项目)

文章目录 一、抽屉半自动点赞二、xpath的使用三、动作链四、打码平台介绍超级鹰打码基本测试 五、自动登录超级鹰六、scrapy框架介绍安装创建爬虫项目 一、抽屉半自动点赞 登录抽屉账号保存cookiesimport timeimport jsonfrom selenium import webdriverfrom selenium.webdrive…

基于YOLOv5+PySide6的火灾火情火焰检测系统设计深度学习

wx供重浩:创享日记 对话框发送:225火灾 获取完整源码源文件已标注的数据集(1553张)配置跑起来说明 可有偿49yuan一对一远程操作,在你电脑跑起来 效果展示: ​数据集在下载的文件夹:yolov5-5.0\…

一键生成PDF即刻呈现:轻松创建无忧体验

在信息爆炸的时代,我们每天都在与各种文件、资料打交道。无论是工作中的报告、合同,还是学习中的笔记、论文,如何高效、安全地管理这些珍贵的资料,成为了我们迫切的需求。幸运的是,随着科技的发展,我们不再…

PX4FMU和PX4IO最底层启动过程分析(下)

PX4FMU和PX4IO最底层启动过程分析(下) PX4FMU的系统启动函数为nash_main(int argc,char *argv[]) PX4IO的系统启动函数为nash_start(int argc,char *argv[]) PX4FMU启动函数nash_main(int argc,char *argv[]) 首先分析一下nash_main(int argc,char *a…

五大方法教你如何分分钟构造百万测试数据!

在测试的工作过程中,很多场景是需要构造一些数据在项目里的,方便测试工作的进行,构造的方法有很多,难度和技术深度也不一样。本文提供方法供你选择。 在测试的工作过程中,很多场景是需要构造一些数据在项目里的&#…

【《高性能 MySQL》摘录】第 2 章 MySQL 基准测试

文章目录 2.1 为什么需要基准测试2.2 基准测试的策略2.2.1 测试何种指标 2.3 基准测试方法2.3.1 设计和规划基准测试2.3.2 基准测试应该运行多长时间2.3.3 获取系统性能和状态2.3.4 获得准确的测试结果2.3.5 运行基准测试并分析结果2.3.6 绘图的重要性 2.4 基准测试工具…

vue3 实现 el-pagination页面分页组件的封装以及调用

示例图 一、组件代码 <template><el-config-provider :locale"zhCn"><el-pagination background class"lj-paging" layout"prev, pager, next, jumper" :pager-count"5" :total"total":current-page"p…

深入浅出JVM(十)之字节码指令(下篇)

上篇文章深入浅出JVM&#xff08;九&#xff09;之字节码指令&#xff08;上篇&#xff09;已经深入浅出说明加载存储、算术、类型转换的字节码指令&#xff0c;本篇文章作为字节码的指令的下篇&#xff0c;深入浅出的解析各种类型字节码指令&#xff0c;如&#xff1a;方法调用…