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 ...
随机推荐
- Mysql常用sql语句(5)- as 设置别名
测试必备的Mysql常用sql语句系列 https://www.cnblogs.com/poloyy/category/1683347.html 需要注意,创建数据库和创建表的语句博文都在前面哦 整个 ...
- Excel导入保存附件和解析数据
Excel导入保存附件和解析数据 一,前端上传附件的组件 1.先给一个下载模板的按钮 // 下载Excel模板 downLoadExcel: function () { window.open(GLO ...
- Java学习笔记--常用容器
容器 1. 出现原因 解决程序运行时需要创建新对象,在程序运行前不知道运行的所需的对象数量甚至是类型的问题. Java中提供了一套集合类来解决这些问题包括:List.Set.Queue.Map 2. ...
- easyx实现小球移动
easyx是一个针对VC++编译器的图形化插件.使用它,可以使得在C++中编写图形程序. 小球移动代码: #include"stdafx.h" #include<graphi ...
- python线程threading
线程示例: import threading import time # 唱歌任务 def sing(): # 扩展: 获取当前线程 # print("sing当前执行的线程为:" ...
- 2021“MINIEYE杯”中国大学生算法设计超级联赛(7)部分题解
前言 找大佬嫖到个号来划水打比赛了,有的题没写或者不是我写的就不放了. 目前只有:1004,1005,1007,1008,1011 正题 题目链接:https://acm.hdu.edu.cn/con ...
- 使用jacob调用Windows的com对象,进行word、ppt等转换成ptf、html(二)
富文本转pdf : 注意:simsun.ttc 可以百度下载:http://www.pc6.com/softview/SoftView_100415.html package com.orangecd ...
- DBeaver MSSQL 支持TLS设置
DBeaver是一个基于 Java 开发,免费开源的通用数据库管理和开发工具,使用非常友好的 ASL 协议.可以通过官方网站或者 Github 进行下载. 由于 DBeaver 基于 Java 开发, ...
- NOIP 模拟九 考试总结
T1 考场上先干的T2,最后慌慌张张没去想正解,打算把树建起来,拿70分的部分分,于是写树剖LCA,板子好像忘了,回忆了好久还模拟了好几遍才打对树剖LCA............期望70,结果0.考试 ...
- firewalld dbus接口使用指南
firewalld,一个基于动态区的iptables/nftables守护程序,自2009年左右开始开发,最新版本 - 防火墙0.6.3 - 发布于2018年10月11日.主要的开发人员是托马斯·沃纳 ...