前言
什么分布式事务?
随着互联网的快速发展,软件系统由原来的单体应用转变为分布式应用,分布式系统会把一个应用系统拆分为可独立部署的多个服务,因此需要服务与服务之间远程协作才能完成事务操作,这种分布式系统环境下由不同的服务之间通过网络远程协作完成事务称之为分布式事务,例如用户注册送积分事务、创建订单减库存事务,银行转账事务等都是分布式事务。
分布式事务产生的场景
例1:典型的场景就是微服务架构 微服务之间通过远程调用完成事务操作。
比如:订单微服务和库存微服务,下单的同时订单微服务请求库存微服务减库存。 简言之:跨JVM进程产生分布式事务。
例2:单体系统访问多个数据库实例 当单体系统需要访问多个数据库(实例)时就会产生分布式事务。
比如:用户信息和订单信息分别在两个MySQL实例存储,用户管理系统删除用户信息,需要分别删除用户信息及用户的订单信息,由于数据分布在不同的数据实例,需要通过不同的数据库链接去操作数据,此时产生分布式事务。 简言之:跨数据库实例产生分布式事务。
如何解决分布式事务
根据CAP和BASE理论,分布式事务解决的核心思想主要是:无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性,而最终一致性涉及到方式主要是二阶段提交和三阶段提交。
目前主要解决分布式事务的方式是通过RocketMQ或者阿里推出的SEATA框架解决,本文主要是通过RocketMQ实操来处理分布式事务的场景。
RocketMQ 基本使用
关于RocketMQ的基本的消息发送方式和消息类型,大家可以到官网自行学习:RocketMQ官网文档,MQ解决分布式事务主要是通过事务消息的方式来解决。
实操
因为这篇文章主要是针对分布式事务,所以建表和业务逻辑不是十分严谨,不过作者会尽可能的保证分布式事务、MQ使用的严谨性。
场景
场景比较简单,主要是一个跨行转账的操作,例:手机号为XXX的用户将钱从农行转到华夏银行。
建表
数据库test:存在表abc_person、transfer_detail
建表sql:
CREATE TABLE `abc_person` (
`user_id` int(11) NOT NULL COMMENT '用户编号',
`name` varchar(20) DEFAULT '' COMMENT '用户名称',
`id_card` varchar(20) DEFAULT NULL COMMENT '身份证号',
`banlance` decimal(10,2) DEFAULT NULL COMMENT '余额',
`mobile` varchar(12) DEFAULT '' COMMENT '手机号',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`delete_flg` char(1) DEFAULT '0' COMMENT '删除状态',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';
CREATE TABLE `transfer_detail` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '明细ID',
`user_id` int(11) NOT NULL DEFAULT '0' COMMENT '用户ID',
`money` decimal(10,2) DEFAULT '0.00' COMMENT '转账金额',
`msg_id` varchar(50) DEFAULT '' COMMENT '消息ID',
`delete_flg` char(1) DEFAULT '0' COMMENT '是否删除状态',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET&#