Springcloud seata分布式事务实现代码解析
作者:梦泽千秋 发布时间:2022-12-27 20:14:01
Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。本篇不涉及其原理,只用代码构建项目简单试用一下其回滚的机制。
大致上seata分为TC,TM,RM三大构建成整体。它们之间的包含关系如下。即一(xid主键编码,记录信息)带三(TC,TM,RM)
下面之间构建项目进行测试。
1.下载seata并解压,然后改动配置文件。
http://seata.io/zh-cn/blog/download.html官网下载。
解压之后到conf中修改file和registry文件,修改之前一定记得先备份。
file.conf,改动两个地方
将group后面的参数定义一个名字,随意
存储方式选db放在数据库,自然其配置信息根据自己的数据库去填写。
然后是register文件,填写信息将seata注册到nacos中。
启动自然是在bin中打开bat文件即可,注意需要先启动naco。
2.构建项目(order,storage,account)
演示整体的服务调用还有服务报错的时候进入回滚。通过创建订单->检查库存并扣除->检查账户并扣除->修改订单状态
具体代码可查看GitHub
https://github.com/MaTsukun/springcloud2020
关键的service方法
@Service
@Slf4j
public class OrderServiceImpl implements OrderService{
@Resource
private OrderMapper orderMapper;
@Resource
private StorageService storageService;
@Resource
private AccountService accountService;
@Override
@GlobalTransactional(name="abc-create-order",rollbackFor = Exception.class)
public void create(Order order){
//1.创建订单
log.info("开始创建订单");
orderMapper.create(order);
//2.减少库存
log.info("查询库存并且进行更改");
storageService.decrease(order.getProductId(),order.getCount());
//3.扣除费用
log.info("查询余额并扣除费用");
accountService.updateAccount(order.getUserId(),order.getMoney());
//4.修改状态
log.info("更改订单状态");
orderMapper.update(order.getUserId(),0);
log.info("订单结束,O(∩_∩)O哈哈~");
}
}
可以看到在order项目中同时调用了storage和account的项目的方法,采用的是openfeign,整体形成了一个链路,成为一个整的事务。
而添加的GlobalTransactional注解则保证了事务中任何一方出现错误就会使整个项目的执行过程进行回滚,而不是单事务的回滚。
3.seata回滚原理
在每次注解的方法里进行执行sql语句的时候都会创建一个id记录此次的写操作同时在每次的写操作前后都会生成前置记录和后置记录,可以在出现错误回滚的时候,通过记录进行逆操作回滚重新将数据写回去。
通过数据库配置的seata库展示可以看见对应的记录id信息,通过debug模式暂停服务,查看记录的信息。
global的全局xid
account表的undo记录
记录的信息json格式
{
"@class": "io.seata.rm.datasource.undo.BranchUndoLog",
"xid": "192.168.2.141:8091:2060193863",
"branchId": 2060193875,
"sqlUndoLogs": [
"java.util.ArrayList",
[
{
"@class": "io.seata.rm.datasource.undo.SQLUndoLog",
"sqlType": "UPDATE",
"tableName": "t_account",
"beforeImage": {
"@class": "io.seata.rm.datasource.sql.struct.TableRecords",
"tableName": "t_account",
"rows": [
"java.util.ArrayList",
[
{
"@class": "io.seata.rm.datasource.sql.struct.Row",
"fields": [
"java.util.ArrayList",
[
{
"@class": "io.seata.rm.datasource.sql.struct.Field",
"name": "id",
"keyType": "PrimaryKey",
"type": -5,
"value": [
"java.lang.Long",
1
]
},
{
"@class": "io.seata.rm.datasource.sql.struct.Field",
"name": "used",
"keyType": "NULL",
"type": 3,
"value": [
"java.math.BigDecimal",
600
]
},
{
"@class": "io.seata.rm.datasource.sql.struct.Field",
"name": "residue",
"keyType": "NULL",
"type": 3,
"value": [
"java.math.BigDecimal",
400
]
}
]
]
}
]
]
},
"afterImage": {
"@class": "io.seata.rm.datasource.sql.struct.TableRecords",
"tableName": "t_account",
"rows": [
"java.util.ArrayList",
[
{
"@class": "io.seata.rm.datasource.sql.struct.Row",
"fields": [
"java.util.ArrayList",
[
{
"@class": "io.seata.rm.datasource.sql.struct.Field",
"name": "id",
"keyType": "PrimaryKey",
"type": -5,
"value": [
"java.lang.Long",
1
]
},
{
"@class": "io.seata.rm.datasource.sql.struct.Field",
"name": "used",
"keyType": "NULL",
"type": 3,
"value": [
"java.math.BigDecimal",
700
]
},
{
"@class": "io.seata.rm.datasource.sql.struct.Field",
"name": "residue",
"keyType": "NULL",
"type": 3,
"value": [
"java.math.BigDecimal",
300
]
}
]
]
}
]
]
}
}
]
]
}
可以看到里面有beforeimage和afterimage快照记录,通过这些记录可以实现逆操作,重新写进数据实现回滚。
本文只是简单的配置,后续会进行详细补充。
所有的代码都在GitHub
https://github.com/MaTsukun/springcloud2020
来源:https://www.cnblogs.com/lin530/p/14048973.html


猜你喜欢
- 最近过年发红包拜年成为一种新的潮流,作为程序猿对算法的好奇远远要大于对红包的好奇,这里介绍一种自己想到的一种随机红包分配策略,还请大家多多指
- Vector的基本介绍1.:Vector类的定义:public class Vector<E> ext
- 给Word文档设置背景时,通常只能针对整篇文档设置统一的背景,如果需要对某些页面单独设置背景,则需要通过另外的方式来实现。本文通过C# 程序
- 本文实例为大家分享了Android读取NFC卡的编号具体代码,供大家参考,具体内容如下NFC相关androidManifest文件设置:一、
- 错误示例,同一个类中使用异步方法:package com.xqnode.learning.controller;import com.fas
- 题目给定count=0;让5个线程并发累加到1000;思路创建一个类MyRunnable,实现Runnable(继承Thread类也可)定义
- 使用filter对response内容进行加密编写加密类(AES)/** * aes加密解密 */public class AesEncry
- 下文我们介绍两种双击事件拦截的方式1.通过Android的事件分发机制进行拦截(dispatchTouchEvent)话不多说,直接上代码:
- 工厂方法模式,往往是设计模式初学者入门的模式,的确,有人称之为最为典型最具启发效果的模式。android中用到了太多的工厂类,其中有用工厂方
- 条件:1、android:ellipsize=”marquee”2、TextView必须单行显示,即内容必须超出TextView
- 前言在我们java开发中,Date日期这个字段会被经常使用,比如获取当前系统的时间,获取上个月,上一年的时间,以及获取两个日期相差的时分秒数
- //加载Excel public 
- 前言 SpringCloud 是微服务中的翘楚,最佳的落地方案。 在微服务架构中多层服务之间会相互调用,如果其中有一
- 详解 Corba开发之Java实现Service与Client1 概述
- 前 言最近和我们老大一起做技术面试(我是旁听的),发现前来面试的没几个掌握甚至是丁点了解LINQ。这让我很纳闷,LINQ伴随2008一起发布
- 无论使用何种IDE开发Android,集成官方Android SDK并创建Android工程之后,该工程都会默认包括一整套Android项目
- 近日于LeetCode看题遇1114 按序打印,获悉一解法使用了Semaphore,顺势研究,记心得于此。此解视Semaphore为锁,以保
- 本文实例为大家分享了java使用字符画一个海绵宝宝的具体代码,供大家参考,具体内容如下用字符画一个海绵宝宝用" &ldqu
- C++对string进行大小写转换操作方法方法一:使用C语言之前的方法,使用函数,进行转换#include <iostream>
- 本文实例为大家分享了android实现简单拼图游戏的具体代码,供大家参考,具体内容如下1.2.//使用回调接口,首先初始化pintuview