搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
笔触狂放9
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
数据挖掘算法——关联分析算法(apriori和FPgrowth)_数据挖掘(关联规则(fp-growth、apriori)、分类(决策树、k-近邻、朴素贝叶斯)、聚
2
关于IDEA(VScode)中github push时连接失败的问题解决_vscode网络原因github访问不到
3
postgresql源码学习(27)—— 事务日志⑦-日志落盘上层函数 XLogFlush
4
【Python入门】Python循环语句(for循环的基础语法)_python for
5
OpenLayers中样式Style,styleMap等的设计分析和使用说明
6
失物招领平台|基于Springboot+Vue实现失物招领系统_springboot和vue工具软件
7
POWERLINK协议在stm32单片机+w5500移植成功经验分享_stm32 w5500
8
写typescript项目时怎么引入第三方包的d.ts声明文件
9
关于微信JAVA家政小程序源码技术实现方案_家政小程序java
10
安装Ubuntu Linux,配套安装宝塔,安装禅道OK!_宝塔安装禅道
当前位置:
article
> 正文
平台转账的设计_转账系统安全描述
作者:笔触狂放9 | 2024-04-11 10:35:08
赞
踩
转账系统安全描述
做个平台间余额的互相转账,重点在于如何解决并发访问数据错乱的问题.比如俩个人之间同时都在给对方转账.以及很多人同时给一个人转账.必须保证数据库里面的数据是随时正确的.
我本没有想到过这一层面,被提醒的.
比如有个转账的方法transfer(业务逻辑主要写在这里)
1.首先想到的用多线程加锁,看了资料.是可以实现,但是问题是对方法加锁或者代码块加锁,那么每次只能执行一个线程,a转给b执行了,可c却不能同时转给d,二者根本不会影响啊.所以多线程白看了.
2.然后就取决在数据库上面了.用的是mysql innodb,所以找了这方面锁的知识.
这篇博客写的不错,感谢:
http://www.cnblogs.com/Arlen/articles/1756616.html
结合其他的参考学习,我总结了一下:
mysql innodb主要有表级锁和行级锁,转账之间不能互相影响,所以选择行级锁.
行级锁有两种:共享锁和排他锁
如何加锁:共享锁:select xxxx lock in share mode
排他锁:select xxx for update
顾名思义共享锁的重点在于多个事务可以同时共享同一资源上的共享锁,如果一个事务获取了一个数据的共享锁,那么别的事务也可以再获取这个锁.获取共享锁的事务可以对数据进行读操作.,读完了就释放.
排他锁就是一旦事务获取了这个锁,他就必须持有这个锁到结束,并不准其他事务获取这个锁.持有排他锁的事务可以对数据进行写操作.
然后明确一点一个事务在一个时刻里只能拥有一把锁
在转账时如果我先查找用户的账户信息,如果我用共享锁的话,别的事务也可以共享这个锁,这时候就会产生死锁.
这里的死锁产生的原因在于:
当A向B转账的时候,B也在向C转账,A开始转账的时候获取A,B账户信息,A开始转账的时候获取C,B账户信息,这里是共享锁,然后我需要对账户进行更新,这时候问题就出现了;
假如A转账在准备更新B的信息时,发现B转账也准备更新B,A就等B释放共享锁,B也等A在释放共享锁,也就产生死锁了.
如果没有,那么在查询完后,A事务就释放了共享锁,然后这时候别的B事务就可以获取这个用户账户信息的共享锁,
假如B获取了.那A了刚刚查出来了用户信息,想改的时候(mysql修改默认加上排他锁)发现资源又被锁了.给别人挪用了.别人对他干了啥我哪知道,以后数据就肯能和我刚读出来的不一样了.
排它锁事务一旦获取了就一直到事务结束都会拥有这把锁,这样就很好的杜绝了数据被修改的可能性.那么这时候重点就在于这里的事务怎么开始和啥时候结束了.我的项目用的是springMVC,就是spring的事务是怎么确定的.
这篇博客写的不错,感谢:
http://www.cnblogs.com/davidwang456/p/3832949.html
这里不需要知道spring事务的深层原理,只需知道spring事务是在进入sercice层执行方法的时候开始定义一个事务,然后在这个方法结束后事务才结束(事务提交).就是说在这个方法里面不管调用了多少个dao方法,都不会影响锁的丢失.也就是说我进入方法查询用户加了排他锁,在这个方法结束之前该数据就是安全的.
好了理论说完了,看程序了:
这是我的service方法
@Transactional(readOnly=false)
public int transfer(String userId, String money, String remarks,
String otherId) {
HcUser me = this.userDao.getUserForUpdate(userId);//获取用户信息
HcUser other = this.userDao.getUserForUpdate(otherId);//获取用户信息
//这里写转账的一些操作(修改/插入等)
return 0;
}
这是mybatis的sql:
<select id="getUserForUpdate" parameterType="java.lang.String" resultType="HcUser">
select *
from hc_user
where id=#{id}
for update <!-- 这里加锁-->
</select>
写的是web项目,需要在浏览器敲地址测试,但是无法实现多线程,于是可以这样:
用java写访问url的程序(网上找的拉):
package examples;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.commons.lang3.RandomUtils;
public class TEST {
public static void main(String args[]) {
for(int i = 0;i <400; i++) {//设置400个线程
String money =RandomUtils.nextInt(1, 5)+"";
System.out.println(money);
//模拟几个用户
String userId = "2aefe0c4c88f4ea1b39a68b6e33208d8";
String otherId="1bb4fc7d35c342a3a19bc23171aa3d22";
String userId1="1b638bd7dbb445a3bfe1efbec1a61e4e";
String userId2="551926783cb64524b3127ec02529d371";
Account a = null;
//设置不同的转账
if("1".equals(money)) {
a = new Account(money,userId,otherId);
}
else if("2".equals(money)) {
a = new Account(money,userId1,userId);
}else if("3".equals(money)) {
a = new Account(money,userId2,userId);
}
else {
a = new Account(money,userId1,otherId);
}
Thread t = new Thread(a);
t.start();
}
}
static class Account implements Runnable {
String money = "0";
String userId = "";
String otherId="";
public Account(String money,String userId,String otherId) {
this.money = money;
this.otherId = otherId;
this.userId = userId;
}
@Override
public void run() {
long begintime = System.currentTimeMillis();
try {
URL url = new URL("
http:xxx?userId=
"
+userId+"&otherId="+otherId+"&remarks=xxx"
+"&money="+money);
HttpURLConnection urlcon = (HttpURLConnection)url.openConnection();
urlcon.connect(); //获取连接
InputStream is = urlcon.getInputStream();
BufferedReader buffer = new BufferedReader(new InputStreamReader(is));
StringBuffer bs = new StringBuffer();
String l = null;
while((l=buffer.readLine())!=null){
bs.append(l).append("/n");
}
System.out.println(bs.toString());//打印出信息
System.out.println("总共执行时间为:"+(System.currentTimeMillis()-begintime)+"毫秒");
}catch(IOException e){
System.out.println(e);
}
}
}
}
这样写的程序可能出现有两个线程同时进行A给B转账,请先不要在意这种情况.
这是我数据库账户初始值,每人设置100:
1,在不加锁的情况下,跑完后:
总额变小了扇
2,加了共享锁,跑完后:
总额是对的,但是报错了:
Deadlock found when trying to get lock; try restarting transaction;
产生死锁了,但是mysql会自己强制性重启事务,所以不会一直死锁下去,程序之后还会运行.
3加了排他锁后:
没有错误,正确运行
这样就可以保证转账正确运行了,
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/笔触狂放9/article/detail/404476
推荐阅读
article
MySql
InnoDB
存储引擎表
优化
...
适时的使用 OPTIMIZE TABLE 语句来重组表(表数据到达一定的量,或者有了较大的数据增长之后),压缩浪费的表空...
赞
踩
article
Prometheus
接入
AlterManager
配置
邮件
告警
(基于
K8S
环境部署)...
基于。
Prometheus
接入
AlterManager
配置
邮件
告警
(基于
K8S
环境部署) ...
赞
踩
article
ML之
回归
预测:
机器
学习中的
各种
Regression
回归
算法
、
关键步骤
配图_
回归
算法
的统计预报技术路...
ML之
回归
预测:
机器
学习中的
各种
Regression
回归
算法
、
关键步骤
配图目录
机器
学习中的
各种
回归
算法
1、
回归
算法
代码2...
赞
踩
article
Linux
平台利用
Ollama
和
Open
WebUI
部署大模型_
open
webui
如何添加模型(...
为了做好运维面试路上的助攻手,特整理了上百道。_
ollama
网址访问
ollama
网址访问 ...
赞
踩
article
【
鸿蒙
开发
】 “
极简
”
搭建
鸿蒙
开发
环境
(南向)
_
vscode
鸿蒙
...
系统
环境
:WIN10+VM(Ubuntu21.04)
开发
工具:VSCode+DevEcoDeviceTool插件 ...
赞
踩
article
3.
机器
学习
-十大
算法
之一
线性
回归
算法
(LinearRegression)原理讲解_linearre...
线性
是指一种关系或者过程,其特点是当输入发生变化时,输出会以同样的比例变化。简单来说,
线性
是指两个变量之间存在着直接的比...
赞
踩
article
深度
学习
框架
中张量的
执行
过程...
本文重点介绍
深度
学习
框架
中张量
执行
背后发生的情况。以操作符oneflow.relu为例,介绍
执行
该操作符需要依赖的Int...
赞
踩
article
Zynq
开发板
FPGA
比特流
文件下载方式...
Zynq
开发板
FPGA
比特流
文件可以通过三种途径下载:1. 利用SDK生成的FSBL.elf文件自动加载
FPGA
比特流
配...
赞
踩
article
My
SQL
常用
函数
...
一、数学
函数
数学
函数
主要用于处理数字,包括整型、浮点数等。ABS(x) 返回x的绝对值 SELECT ABS(-...
赞
踩
article
Git
Hub
超详细图文攻略 -
Git
客户端下载安装
Git
Hub
提交修改源码工作流程
Git
分支 ...
Git
Hub
操作总结 : 总结看不明白就看下面的详细讲解.
Git
Hub
操作流程 :第一次提交 : -- 初始化git仓库...
赞
踩
article
HarmonyOS
实战
开发
-
设备
管理
合集(非
系统
特性
)...
本示例集合
设备
管理
相关(非
系统
特性
)不需要复杂功能展示的模块,展示了各个模块的基础功能,包含:
HarmonyOS
实战
开发
...
赞
踩
article
java
模拟
银行
账户
业务
转账
_
模拟
银行
账户
汇款操作(并发控制)...
import
java
.util.Arrays;import
java
.util.concurrent.CountDow...
赞
踩
article
Netty
+
Vue
实现
一个
简单的web
服务器
_
vue
netty
...
最近一直在用
Netty
做
一个
数据服务,此服务的主要功能是接收客户端的Http请求并解析,经过业务逻辑处理后访问HBase...
赞
踩
article
神经网络
:
前
向
传播
和后
向
传播
...
数学角度的解释需要使用链式法则和梯度计算,涉及到矩阵乘法、偏导数等运算,具体的推导和数学公式较为复杂,超出了当前文本输入...
赞
踩
article
【
运维
工程师
必备技
能
之一】——
英语
基础
_
英语
不好
能
做好
运维
吗...
运维
工程师
入门必备
基础
_
英语
不好
能
做好
运维
吗
英语
不好
能
做好
运维
吗 ...
赞
踩
article
2021
年最新
外卖
侠
cps
小
程序
,
三级
分销
返利
外卖
领劵
小
程序
源码
,
带电影票
分销
积分商城(
外卖
侠重要功...
最近超火的
外卖
cps
小
程序
,
分享红包就能得佣金
,
三级分佣
,
超强裂变吸粉神器1、全部可对接自己的CPS渠道
,
美团可对接美团...
赞
踩
article
面向对象
软件设计
原则
_软件
面向对象
原则
...
n 单一职责
原则
(SRP)就一个类而言,应该仅有一个引起它变化的原因。n 开放-封闭
原则
(OCP)软件实体应该是可以...
赞
踩
article
git
提交报错
error
:
failed
to
push
some
refs
to ‘
git
url...
想把本地仓库提交到远程仓库,报错信息如下
git
提交报错信息错误原因:我们在创建仓库的时候,都会勾选“使用Reamdme文...
赞
踩
article
Spring
事务
传播
属性
介绍(二).
mandatory
、not_supported、
never
、su...
Required、Required_New
传播
属性
分析传送门:https://www.cnblogs.com/lvbin...
赞
踩
article
玩转
OurBMC
第三期:
OpenBMC
的
构建
与
开发
流程_
bmc
开发
教程...
本期内容我们将为您详细介绍在 Linux 环境下编译
构建
OpenBMC
的
步骤,以及如何使用 devtool 工具修复...
赞
踩
相关标签
mysql
adb
数据库
kubernetes
prometheus
容器
linux
运维
服务器
华为
算法
机器学习
线性回归
oneflow
张量的执行过程
深度学习
github
源码
版本控制工具
harmonyos
OpenHarmony
鸿蒙应用开发
鸿蒙开发
鸿蒙