Seata分布式事务失败通知
一、背景
在我们使用Seata
作为分布式事务时,有些时候我们的分布式时候并不是每次都可以成功的,而对于这些失败的分布式事务就需要进行通知。这篇文章简单记录一下如何实现通知。
二、功能实现
- 此处模拟邮件通知,但是不真正发送邮件,只是简单记录一个日志。
三、注意事项
1、 假设我们的分布式事务回滚失败,在AT
模式中是会锁定表记录数据的。后期需要获取这条记录的全局锁
操作,都会失败。
举例:
假设存在如下数据表记录数据
账号 | 金额 |
---|---|
zhangsan | 100 |
zhangsan
这条记录参与分布式事务。
- 在分布式事务中将 zhangsan 的金额修改成 90.
- 另外一个同事,直接操作数据库,将 zhangsan 的记录修改成 80. (此时是可以修改成功的,因为 Seata 是二阶段提交,在第一阶段结束后,会释放记录的本地锁,不释放记录的全局锁)
- 接下来继续别的分布式事务操作,但是发生了异常,此时分布式事务会回滚失败,因为 zhangsan 的金额变成了80,和之前的对应不上。
- 如果再次对 zhangsan 进行分布式事务操作或者需要获取全局锁的操作,那么都会失败。
四、实现步骤
1、编写一个类实现FailureHandler接口
FailureHandler
的全类名为:io.seata.tm.api.FailureHandler
,它有一个默认的实现DefaultFailureHandlerImpl
, 此处我们写一个类继承这个类。
package com.huan.seata.handler;
import io.seata.tm.api.DefaultFailureHandlerImpl;
import io.seata.tm.api.GlobalTransaction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* Seata 分布式事物失败的处理
*
* @author huan.fu 2021/10/8 - 下午1:51
*/
@Component("failureHandler")
@Slf4j
public class EmailSeataFailureHandler extends DefaultFailureHandlerImpl {
@Override
public void onBeginFailure(GlobalTransaction tx, Throwable cause) {
super.onBeginFailure(tx, cause);
log.warn("邮件通知:分布式事物出现异常:[onBeginFailure],xid:[{}]", tx.getXid());
}
@Override
public void onCommitFailure(GlobalTransaction tx, Throwable cause) {
super.onCommitFailure(tx, cause);
log.warn("邮件通知:分布式事物出现异常:[onCommitFailure],xid:[{}]", tx.getXid());
}
@Override
public void onRollbackFailure(GlobalTransaction tx, Throwable originalException) {
super.onRollbackFailure(tx, originalException);
log.warn("邮件通知:分布式事物出现异常:[onRollbackFailure],xid:[{}]", tx.getXid());
}
@Override
public void onRollbackRetrying(GlobalTransaction tx, Throwable originalException) {
super.onRollbackRetrying(tx, originalException);
log.warn("邮件通知:分布式事物出现异常:[onRollbackRetrying],xid:[{}]", tx.getXid());
}
}
2、加入到Spring中的BeanName的值
在测试的时候发现FailureHandler
加入到Spring中的beanName必须是failureHandler
,否则报错,是seata的自动配置中如下代码决定的。
BEAN_NAME_FAILURE_HANDLER
常量的值为 failureHandler
/**
* 源码
* The type Seata auto configuration
*/
@ConditionalOnProperty(prefix = SEATA_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
public class SeataAutoConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(SeataAutoConfiguration.class);
@Bean(BEAN_NAME_FAILURE_HANDLER)
@ConditionalOnMissingBean(FailureHandler.class)
public FailureHandler failureHandler() {
return new DefaultFailureHandlerImpl();
}
@Bean
@DependsOn({BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER, BEAN_NAME_FAILURE_HANDLER})
@ConditionalOnMissingBean(GlobalTransactionScanner.class)
public GlobalTransactionScanner globalTransactionScanner(SeataProperties seataProperties, FailureHandler failureHandler) {
if (LOGGER.isInfoEnabled()) {
LOGGER.info("Automatically configure Seata");
}
return new GlobalTransactionScanner(seataProperties.getApplicationId(), seataProperties.getTxServiceGroup(), failureHandler);
}
}
五、测试
访问curl -X GET http://localhost:50027/createOrder\?accountId\=1\&amount\=10\&hasException\=true
,然后手动打断点,修改数据库数据,使数据不一致,然后代码跑出异常,此处回滚失败,因为undo_log表中的数据对不起来。
六、完整代码
https://gitee.com/huan1993/spring-cloud-parent/tree/master/seata/seata-springboot-failure-handler
Seata分布式事务失败通知的更多相关文章
- Dubbo学习系列之十五(Seata分布式事务方案TCC模式)
上篇的续集. 工具: Idea201902/JDK11/Gradle5.6.2/Mysql8.0.11/Lombok0.27/Postman7.5.0/SpringBoot2.1.9/Nacos1.1 ...
- SpringCloud微服务实战——搭建企业级开发框架(二十七):集成多数据源+Seata分布式事务+读写分离+分库分表
读写分离:为了确保数据库产品的稳定性,很多数据库拥有双机热备功能.也就是,第一台数据库服务器,是对外提供增删改业务的生产服务器:第二台数据库服务器,主要进行读的操作. 目前有多种方式实现读写分离,一种 ...
- Seata–分布式事务
10.1 分布式事务基础 10.1.1 事务 事务指的就是一个操作单元,在这个操作单元中的所有操作最终要保持一致的行为,要么所有操作都成功,要么所有的操作都被撤销.简单地说,事务提供一种"要 ...
- 5-4 Seata 分布式事务管理
下载Seata https://github.com/seata/seata/releases https://github.com/seata/seata/releases/download/v1. ...
- Dubbo学习系列之十四(Seata分布式事务方案AT模式)
一直说写有关最新技术的文章,但前面似乎都有点偏了,只能说算主流技术,今天这个主题,我觉得应该名副其实.分布式微服务的深水区并不是单个微服务的设计,而是服务间的数据一致性问题!解决了这个问题,才算是把分 ...
- SEATA 分布式事务入门DEMO
Simple Extensible Autonomous Transacation Architecture,seata是简单的.可扩展.自主性高的分布式架构 SEATA Server Configu ...
- spring boot:shardingsphere+druid多数据源整合seata分布式事务(spring boot 2.3.3)
一,为什么要给shardingsphere配置多数据源? 1,shardingjdbc默认接管了所有的数据源, 如果我们有多个非分表的库时,则最多只能设置一个为默认数据库, 其他的非分表数据库不能访问 ...
- spring boot:shardingsphere+druid整合seata分布式事务(spring boot 2.3.3)
一,shardingshpere为什么要整合seata? 分库分表是数据库扩展中最常用的处理方法, shardingshpere作为使用最广泛的分表中间件, 如果不支持分布式事务,则它的数据一致性就会 ...
- Seata分布式事务框架Sample
前言 阿里官方给出了seata-sample地址,官方自己也对Sample提供了很多类型,可以查看学习. 我这里选择演示SpringBoot+MyBatis. 该聚合工程共包括5个module: sb ...
随机推荐
- Linux原始套接字抓取底层报文
1.原始套接字使用场景 我们平常所用到的网络编程都是在应用层收发数据,每个程序只能收到发给自己的数据,即每个程序只能收到来自该程序绑定的端口的数据.收到的数据往往只包括应用层数据,原有的头部信息在传递 ...
- (1)java Spring Cloud+Spring boot+mybatis企业快速开发架构之微服务是什么?它的优缺点有哪些?
"微服务"一词来源于 Martin Fowler 的<Microservices>一文.微服务是一种架构风格,即将单体应用划分为小型的服务单元,微服务之间使用 HT ...
- SQL:1999基本语法
SQL:1999基本语法 SELECT [DISTINCT] * | 列名称 [AS]别名,........ FROM 表名称1 [别名1][CROSS JOIN表名称2 别名2]| [NATURAL ...
- freeswitch编译安装依赖
ncurses:提供字符界面 zlib:数据压缩 libjpeg:JPEG图片格式数据的解码/编码/其他. lua:lua解释器 libedit:一种编辑操作的库,对一些可以交互操作的场景,或转为了自 ...
- centos7 下安装 mysql5.7
由于CentOS7的yum源中没有mysql,需要到mysql的官网下载yum repo配置文件. 下载命令: wget https://dev.mysql.com/get/mysql57-commu ...
- 【原创】【长期更新】【未完待续】自制vector类型
继<自制string类型>以来的第二篇自制类型的文章.马上要开学了,时间也不多了,争取在今年写完吧. 目录 一,vector类型简单介绍 1.简介 1.1.STL 1.2.vector 2 ...
- javascript 数组 shuffle 洗牌 打乱顺序
* php shuffle 打乱数组顺序 Array.prototype.shuffle = function () { "use strict"; var a = [], b = ...
- win10家庭版 不能远程登录 windows 10 mstsc不可用
Windows10家庭版的用户,因为系统中没有组策略编辑器,需要修改注册表来实现. 注册表路径:HKLM\Software\Microsoft\Windows\CurrentVersion\Polic ...
- linux环境下,使用Navicat连接mysql时,提示本地IP无法连接虚拟环境下的mysql解决方案
在Linux环境下,使用Navicat连接mysql时,提示本地IP无法连接虚拟环境下的mysql,提示如下: 而导致连接错误的原因是MYSQL没有开启远程登录权限. 解决方案: 在mysql命令中执 ...
- 51nod1675-序列变换【莫比乌斯反演】
正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId=1675 题目大意 给出两个长度为\(n\)的序列\(a,b\),求有多少对 ...