手写分布式事务的一种回滚方案。

news2025/2/21 20:26:36

1:项目架构

      我一个朋友的公司基于实际业务的考虑,选择了多个单体项目来组建成一个分布式系统。(对于目前来说分布式的系统最好采用微服务的架构来实现项目搭建。但基于许多客户只能采用内网的使用,微服务反而会影响项目的复杂度,技术只是为业务服务,适合自己的才是最好的。所以就最终选择了多个SpringBoot项目使用(http请求+mq请求)来组件成分布式系统)。

2:业务背景

举例:在一个场景下,一个客户冲了10块钱,奖励给10个积分。然后获取用户的积分数量来扣减本次的支付金额。

成功的流程图如下:

       在上图中可以看到,每一个步骤都有可能修改了自己系统的数据,如果此时一个系统出现了故障,那么基于单体SpringBoot的事务就只能回滚自己的系统数据。另一个系统无法感知事务异常。所以就会导致数据的错误。

支付异常的流程图如下:

 

3:解决方案

     上文说了,由于客户原因,微服务架构不适用与本系统。所以采用了自己编写回滚方案来解决两个分布式系统的事务回滚问题。本方案采用MQ请求+全局事务id+事务日志表来实现数据回滚。

本解决方案是ACID 还是 BASE?

答:属于BASE理论。ACID 和 BASE 是分布式系统中两种不同级别的一致性理论,在分布式系统中,ACID有更强的一致性,但可伸缩性非常差,仅在必要时使用;BASE的一致性较弱,但有很好的可伸缩性,还可以异步批量处理;大多数分布式事务适合 BASE。众多业务中一般不会要求强一致性,只要保证最终一致性就可以了!

详细过程图如下:

 

4:回滚的详细步骤

表结构:

CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `xid` varchar(100) NOT NULL COMMENT '全局事务ID',
  `object_json` text NOT NULL COMMENT '对象json',
  `object_name` varchar(128) NOT NULL COMMENT '对象名',
  `rollback_info` text DEFAULT NULL COMMENT '回滚信息',
  `log_status` int(11) NOT NULL DEFAULT 0 COMMENT '状态,0正常,1全局已完成, 2回滚失败',
  `log_created` datetime(6) NOT NULL COMMENT '创建时间',
  `log_modified` datetime(6) NOT NULL COMMENT '修改时间',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `ux_undo_log` (`xid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COMMENT='全局事务回滚日志表';

1:先通过uuid生成全局事务id。

String xid = UUID.randomUUID().toString();

2:调用积分系统时将积分对象josn化,然后插入到事务日志表。

  SimpleUndoLog simpleUndoLog=new SimpleUndoLog();
  simpleUndoLog.setXid(xid); //全局事务id
  simpleUndoLog.setObjectJson(JSON.toJSONString(integralDO)); //将积分对象json化。
  simpleUndoLog.setObjectName(integralDO.getClass().getName()); //获取积分对象的类名
  simpleUndoLog.setLogCreated(new Date());
  simpleUndoLog.setLogModified(new Date());
  simpleUndoLogMapper.insertSelective(simpleUndoLog); //插入事务日志表

3:支付系统出现异常,在catch代码块中发送mq请求。

try {
      支付失败
    }catch (Exception e){
       //发送带全局事务id的MQ请求
       rocketMQTemplate.convertAndSend("undo_log",event.getXid());
       throw  new RuntimeException(e.getMessage());
     }

4:在积分系统中接收到回滚mq,通过全局事务id查找出对应的json数据,恢复成对象,然后回滚。

@Slf4j
@Service
@RocketMQMessageListener(
        topic = "undo_log",  //接收mq消息的分组
        consumerGroup = "group_undo_log",
        consumeMode = ConsumeMode.ORDERLY
)

@Resource
private SimpleUndoLogMapper simpleUndoLogMapper;

public class UndoLogConsumer implements RocketMQListener<String> {
             //创建事务日志对象
            SimpleUndoLog undoResult=new SimpleUndoLog();
            //MQ传过来的全局事务id
            undoResult.setXid(xid); 
            try {
            //通过事务id查找事务日志表,获取积分快照
           List<SimpleUndoLog> simpleUndoLogs = simpleUndoLogMapper.selectByXid(xid);
           for (SimpleUndoLog simpleUndoLog : simpleUndoLogs) {
                 //获取事务回滚前的快照,进行更新
                 TntegralDO updateDO= JSON.parseObject(simpleUndoLog.getObjectJson(), new TypeReference<TntegralDO>() {});
                 updateMapper.update(updateDO);
                 }
            }catch (Exception e){
                undoResult.setRollbackInfo(e.getMessage());
                undoResult.setLogStatus(UndoEnum.FAIL.getStatus());
                //回滚失败
                simpleUndoLogMapper.updateByXid(undoResult);
            }
            undoResult.setLogStatus(UndoEnum.SUCCESS.getStatus());
            //事务回滚完成
            simpleUndoLogMapper.updateByXid(undoResult);
}

此时就完成了一个完整的分布式系统的异常回滚。

5:该方案的优缺点

优点:该方案实现简单,只需一张快照日志表即可实现通用的各种事务回滚。后续如果出现回滚失败还能通过表状态方便手动处理。

缺点:该方案无法做到分布式事务的高可用,只能勉强达到最终一致性。还有一种可能如果短时间其他操作影响了快照数据也会导致类似CAS中的ABA问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/619574.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32ADC学习(一)

ADC 模拟/数字转换器 常见ADC类型 并联比较型工作示意图 ADC的特性参数 分辨率&#xff1a;ADC能辨别的最小模拟量&#xff0c;用二进制位数来表示。例如3.3V&#xff0c;12位&#xff0c;能辨别的最小模拟量就是&#xff1a;&#xff08;3.3/4096&#xff09;转换时间&#x…

【面试题HTTP中的两种请求方法】GET 和 POST 有什么区别?

GET 和 POST 有什么区别&#xff1f; 1.相同点和最本质的区别1.1 相同点1.2 最本质的区别 2.非本质区别2.1 缓存不同2.2 参数长度限制不同2.3 回退和刷新不同2.4 历史记录不同2.5 书签不同 总结代码示例 GET 和 POST 是 HTTP 请求中最常用的两种请求方法&#xff0c;在日常开发…

练手必备,20个Python实战项目含源代码

“读”代码是不能给你带来任何收益的&#xff0c;正如“读书”一样&#xff0c;如果在读的时候你不琢磨&#xff0c;保管你读完仨月准忘了一大半。真正需要的是去“试”代码&#xff0c;动手去调调代码&#xff0c;改改这改改那&#xff0c;看看把A变成B这个代码的结果会有什么…

c#使用RSA公钥解密

文章目录 前言一、解密函数1、上代码&#xff01;2、传入的字符串不是base64格式 二、在线验证总结 前言 新项目对接第三方&#xff0c;会把用户信息反正url里面rsa加密传过来&#xff0c;拿到后我解密出用户数据&#xff0c;只给了一个公钥&#xff0c;他们用的java、我用的c…

SpringBoot生成RESTful API文档

由于我一开始学习的SpringBoot是3以上版本&#xff0c;所以我这里用到的也是支持和SpringBoot3能够整合的SpringDoc 这里先说一下&#xff0c;其实SpringDoc就是Swagger3版本&#xff0c;我一开始整合的2版本&#xff0c;比较麻烦况且最后SpringBoot程序都启动不了了&#xff0…

怎样书写专业的落地性能测试计划?

目录 引言 什么是性能测试计划 性能测试计划包含的内容 背景 性能目标 压测范围 启停准则 性能指标 系统架构图 压测前准备 工具准备 数据准备 性能设计 监控设计 项目组织架构 成果输出 项目风险分析 引言 测试计划是软件测试流程中的一个重要步骤&#xff0c;它涉及到对软件…

面向教育行业的MDM(移动设备管理)解决方案

什么是面向教育的MDM 学校和教育机构的移动设备管理 &#xff08;MDM&#xff09; 通过将智能设备配置为适合教育用途&#xff0c;支持通过这些设备进行学习。面向教育的 MDM 解决方案允许组织的 IT 管理员或教学人员管理有助于学习的设备&#xff0c;如智能手机、平板电脑、笔…

十三、输出多个立方体并深度测试

第一部分概念 1&#xff09;由来&#xff1a; 深度测试&#xff1a;opengl的深度测试是指在片段着色器执行之后&#xff0c;利用深度缓冲所保存的深度值决定当前片段是否被丢弃的过程。 深度缓冲区和颜色缓冲区是差不多的&#xff0c;有相同的宽高度&#xff0c;并且一般在窗…

实验篇(7.2) 06. 通过安全隧道访问远端内网服务器 (FortiClient-SSL) ❀ 远程访问

【简介】直接映射服务器到公网&#xff0c;没有验证不安全&#xff1b;通过Web浏览器访问远程内网服务器&#xff0c;有验证也安全&#xff0c;但是支持的协议太少。那有没有即安全&#xff0c;又能支持所有协议的访问方法呢&#xff1f;我们来看看SSL VPN的隧道模式。 实验要求…

智能动环监控系统,实时排查机房安全隐患

动环监控系统又称机房动环、机房动力环境监控系统、动环监控等&#xff0c; 是指对各机房的动力、环境、安防进行集中监测。可对监控系统、设备、安全运行状态进行实时监测、通过统计和处理相关数据&#xff0c;及早发现故障&#xff0c;及时通知运维人员处理&#xff1b;实现机…

员工工作服穿戴AI识别算法 yolov5

员工工作服穿戴AI识别算法是基于yolov5python网络模型人工智能技术&#xff0c;员工工作服穿戴AI识别算法对现场人员的工作服穿戴情况进行实时监控&#xff0c;并对违规情况将自动发出警报。我们选择当下YOLO卷积神经网络YOLOv5来进行火焰识别检测。现版本的YOLOv5每个图像的推…

高并发下缓存失效问题(穿透、雪崩、击穿),以及本地锁、Redis分布锁、Redisson锁、SpringCache使用

高并发下缓存失效问题-穿透、雪崩、击穿 1.缓存穿透2.缓存雪崩3.缓存穿透4.加锁4.1 本地锁4.2 Redis分布锁4.3 RedLock 分布式锁-Redisson**4.3.1 整合Redisson实现分布式锁**4.3.2 分布式锁 1&#xff09;分布式锁 - - 可重入锁 2&#xff09;分布式锁 - - 公平锁 3&#xff0…

Spring面试题(基础篇)

目录 一、Spring框架概述 1、什么是Spring&#xff1f; 2、spring优点有哪些&#xff1f; 二、IOC与DI 3、你知道getBean方法的有几种重载方式吗&#xff1f; 4、Spring有几种依赖注入方式&#xff1f; 三、Spring创建对象 5、Spring创建对象有几种方式&#xff1f; 6…

SciencePub学术 | 可再生能源类重点SCIEI征稿中

SciencePub学术刊源推荐: 可再生能源类重点SCI&EI征稿中&#xff01;2区闭源正刊&#xff0c;进展顺利&#xff0c;稳定检索40年以上。信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 可再生能源类重点SCI&EI 【期刊简介】IF&#xff1a;4.0-4.…

Win安装kafka

Win安装kafka 安装zookeeper修改zookeeper 配置文件 安装kafka启动kafka创建topic查看topic命令 用命令发布消息消费命令 安装zookeeper https://zookeeper.apache.org/releases.html 解压到文件夹 同时在解压目录中拆创建 data和 log文件夹 修改zookeeper 配置文件 - 复制 …

小程序多选框问题

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 例如&#xff1a;前端小程序记录错误bug 问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 例如&#xff1a;前端循环数组时页面数据无法显示 <checkbox-group bindchange"…

【greenplum 性能优化】greenplum 数据库集群 如何释放占用内存

无意中发现了一个巨牛的人工智能教程&#xff0c;忍不住分享一下给大家。教程不仅是零基础&#xff0c;通俗易懂&#xff0c;而且非常风趣幽默&#xff0c;像看小说一样&#xff01;觉得太牛了&#xff0c;所以分享给大家。点这里可以跳转到教程。人工智能教程 在Greenplum数据…

想从事UE4开发相关工作,C++学到什么程度可以开始学习针对虚幻4的编程开发呢?

想从事UE4开发相关工作&#xff0c;C学到什么程度可以开始学习针对虚幻4的编程开发呢&#xff1f; 想从事UE4开发相关工作&#xff0c;C是一个必须要熟练掌握的语言。在学习C过程中&#xff0c;需要掌握语法、面向对象编程、数据结构和算法等内容&#xff0c;这些都是开发UE4所…

nginx修改配置文件不生效

1、问题描述 由于需要向其他公司的数据库中推送数据&#xff0c;但是对方公司的服务器只针对某一台服务器开放了端口&#xff0c;公司的datax部署在另外一台服务器中&#xff0c;导致不能正常连接数据库。因此做了nginx&#xff0c;进行两次代理&#xff0c;但是对方服务器突然…

企业——配置两条静态路由

要求1&#xff1a;按照图中要求配置IP地址&#xff0c;使用静态路由实现要求1、2 要求2&#xff1a;pc1访问pc2走下面 要求3&#xff1a;pc2访问pc1走上面&#xff0c;且两条线路互为备份 1.配置接口IP int g0/0/~ ip address ~ 2.配置静态路由&#xff0c;每个路由两条&a…