只需5分钟,深刻理解本地事务状态表方案|分布式事务系列(四)

news2024/11/28 10:53:11

之前我们已经讲过了最基础的CAP、BASE理论,然后介绍了强一致性方案XA、2PC和3PC,然后详细讲述了TCC在生产中的应用场景和原理。本文继续讲解最终一致性方案——本地事务状态表方案。

点击上方“后端开发技术”,选择“设为星标” ,优质资源及时送达

本地事务状态表

本地事务状态表的方案中主要有三种角色:调用方、被调用方、定时任务。

我们都知道,分布式事务之所以很难保证一致性,但是本地事务却可以,就是因为本地事务是存储引擎层面去保证的。比如 MySQL 的InnoDB 引擎中,他的底层用了 RedoLog 和 UndoLog 以及锁等机制确保了这一点。这里对此不再深入作答,具体可以看往期文章。

所以现在思路是这样:我们要利用存储引擎可以保证事务一致性,这就让我们想到了为每一次远程服务的调用生成一条数据,在数据库落盘,利用本地事务的特点来保证一致性。每一条数据都代表一次RPC调用,然后利用重试机制来保证最终一致性。

用一个案例思考

我先不给详细过程,而是带你实际推理一下,掌握学习方法更重要。

这里使用支付和订单项目来举例,本地服务是支付项目,在支付完成后需要使用RPC通知订单支付结果成功,订单更新订单状态。

正常调用流程如下:

35acc061fde1a4edd1379c0dabc9a5d8.png

看起来流程没有毛病,余额如果通知订单失败,本地事务回滚就是了。余额会加上去,订单也没有支付成功。

订单接口超时怎么办?

但是,一个远程连接有有来和去两个过程,如果余额扣减成功,并且订单服务已经收到支付成功的信息,但是订单本地状态更新为支付成功后,接口响应超时,没有成功返回给支付服务怎么办?

这就造成了余额本地事务回退,金额没有扣减,但是订单状态成功的情况。

3a462ee33041d21ad87bfd55d8030d06.png

本地事务状态表核心流程

为了解决数据不一致的情况,根据文章一开始我们提到的BASE理论,以及利用本地事务来保证数据一致的思路。

因为订单接口有可能超时,网络问题我们无法从编码层面解决,但是可以做到有效的补偿。根据BASE理论,一次调用不能一致,那我多次调用不断尝试不就可以了嘛,总不能每次都超时。

所以这就涉及到两个问题:

  1. 订单接口(被调用方)需要支持幂等操作。

  2. 需要有一种机制让系统知道该重试哪些操作,并且这个机制需要保证和余额(被调用方)数据的一致性。

第一个问题很好解决,可以通过订单ID利用唯一键或者Redis来保证支付行为不会被重复处理。

第二个问题提到了一致性和数据记录,那我们直接保存一条本地事务数据到表里就可以了,保存时候记录订单接口的必要参数信息,以及调用成功状态,默认是未成功。

因为要保证本地事务状态表中的数据和余额(被调用方)一致,那我们就需要把事务提交的时机提前到RPC调用前。

因为此时还没有真正发起RPC调用,所以对于表中记录的数据,可以单独启动一个定时任务不断重试。如果通知订单(被调用方)成功就更改状态为已通知,这样以后定时任务就不会再读取这条记录了。如果还不成功就保持状态不变,继续等待下一次尝试。

d98a291991e803d422b6853ffc4d51f4.png

这里的定时任务不断重试体现了最终一致性的思想。

优缺点

当然,本地事务状态表也优缺点并存,具体使用需要根据场景。

优点:

  1. 性能还不错,业务之间没有强依赖。

  2. 实现了最终一致性,适合对数据不一致有一定容忍度的系统。

缺点:

  1. 有一定的业务入侵性。

  2. 每个系统需要有自己的本地事务状态表,难通用。

  3. 实效性并不是很好。

但是,如上这些缺点其实有一些解决的办法。

定时任务不及时怎么办

笔者自己实现了一套简单的本地事务表框架,主要解决了两个问题:业务入侵度高和实效性。

8a0ceaa298122954f8433552f9f3645b.png

这里不说具体代码了,核心思想是:

  1. 将每个需要利用本地事务表方案的接口和参数保存在ThreadLocal中,并且保存状态表数据到MySQL。

  2. 将每个需要利用本地事务表方案的方法用一个自定义注解去做切面。

  3. 利用TransactionSynchronization接口自己实现了commit,afterCompletion等方法,在事务结束的时候读取ThreadLocal中的内容,以做到及时调用对应RPC。

但是还有问题,每次都需要根据不同的事件类型,写不同的业务逻辑,并且还需要在手动写保存到任务表的逻辑,依旧有业务入侵性,还是有点繁琐。

总结

简单总结下流程:

  1. 调用方在本地事务中保存一条待调用状态的数据到本地事务状态表中。

  2. 本地事务提交后马上调用RPC,如果成功就更新状态,如果不成功那就不管。

  3. 在后台启动一个定时任务,定期扫描本地事务状态表中未调用完成的数据,不断尝试调用。如果成功就更新状态,如果失败那就等待下次调用。在失败重试一定次数后触发告警人工介入处理。

对于本地事务表方案,你能做出自己设计的框架吗?如何解决他存在的问题?

加入讨论群是升职加薪第一步!

回复:加群

71286472ea9f1601b2f3a17ac36d6ac9.jpeg

点赞是一种美德,如对您有帮助,欢迎评论和分享,感谢阅读!

面试官:会SQL调优,那你知道索引合并吗?|金三银四系列

2023-03-21

15c1238d2633526a1d4c4cc17b342cb8.jpeg

CAP、BASE理论真的很重要!|分布式事务系列(一)

2023-03-17

a4c822c8a090c62652c07efdf3646115.jpeg

面试官:你是如何预防多线程死锁的?|金三银四系列

2023-03-16

a901211292f66bd5efb19f9d7fd4025c.jpeg

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

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

相关文章

Go基础篇:类型系统

目录 前言✨一、什么是类型?二、类型特性1、静态类型检查2、类型推断 三、类型别名和自定义类型1、类型别名2、自定义类型3、类型别名和自定义类型的区别 四、类型底层结构1、类型元数据2、其他描述信息3、uncommontype 五、小结 前言✨ 前段时间忙着春招面试&#…

JDK1.8下载、安装和环境配置教程

🎉🎉🎉点进来你就是我的人了博主主页:🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔🦾🦾​​​​​​​ 目录 window系统安装java 下载JDK 配置环境变量 …

算法记录 | Day45 动态规划

70.爬楼梯 (进阶) 改为:一步一个台阶,两个台阶,三个台阶,…,直到 m个台阶。问有多少种不同的方法可以爬到楼顶呢? 1阶,2阶,… m阶就是物品,楼顶…

文件的使用

文章目录 1.概念1.1定义:1.2分类1.3文件名 2.文件的使用2.1文件指针2.2开闭函数2.3顺序读写2.3.1何为读写2.3.2读写函数1.字符输出fputc(输出到文件 写到文件中)2.字符输入fgetc(输入到程序 读到程序中)3.文本行函数4.…

别争了,Excel和Access都靠边,WPS也退,划时代电子表格早已出现

电子表格,绝不仅仅只是你看到的样子! 无论是Excel,还是与它抗衡30多年,不分上下的金山WPS,都没能开创出真正划时代意义的电子表格。 揭秘前让我们先简单回顾下电子表格的前世今生,等不及的可直接进度条下拉…

超写实虚拟人制作教程

最近突然吹起一阵虚拟人直播风潮,大概就是找一个虚拟人物,用主播的面部动作来驱动虚拟人来完成头部和表情动作,但我看大部分都是下载的UE5Unreal Eigine 5(Epic公司出品的一款强大的3D创作平台,很多大型3A大作都是用其…

google.common的guava依赖的partition分割产生的浅拷贝问题解决方案

google.common的guava依赖的partition分割产生的浅拷贝问题解决方案 问题背景解决方案Lyric&#xff1a; 说你不爱我 问题背景 使用google.common的guava依赖的partition分割产生的浅拷贝问题&#xff0c;如: 把userList集合分割成每个10000的小集合 List<List> partiti…

vue+gin—— GetcharZp

vuegin—— GetcharZp vuegin—— GetcharZpP1-项目介绍【03:51】P2-项目梳理【29:59】problemusercategorysubmit P3-环境搭建【05:27】P4-整合GIN、GORM【16:20】P5-整合 Swagger【10:01】P6-接口-问题列表【19:34】P7-接口-问题详情【24:06】P8-接口-用户详情【05:36】P9-接…

C++菱形继承(再剖析)

当子类对象给父类对象的时候&#xff0c;怎么找公共的虚基类&#xff08;A&#xff09; 就得通过偏移量来算虚基类的位置 ---------------------------------------------------------------------------------------------------------------------------- 我们来分析一下B…

DBi-Tech Studio Controls 1.6 for .NET Crack

Studio Controls for .NET 为 Windows 开发人员提供了 18 个 .NET 控件&#xff0c;用于 Outlook 风格的调度到管理单元报告、Windows 应用程序导航到现代 UI 设计演示以实现自然的最终用户功能。 Appointment Scheduling、Time Tabling、Day Timer ... 应…

【Unity入门】20.三维向量

【Unity入门】三维向量 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity入门系列博客&#xff0c;所学知识来自B站阿发老师~感谢 &#xff08;一&#xff09;空间向量 &#xff08;1&#xff09;什么是三维向量 为什么会有这么一篇博客呢&#xff1f;主要是三维向量在unity中…

[Redis] 数据结构zset压缩列表实现和跳表实现讲解

&#x1f61a;一个不甘平凡的普通人&#xff0c;致力于为Golang社区和算法学习做出贡献&#xff0c;期待您的关注和认可&#xff0c;陪您一起学习打卡&#xff01;&#xff01;&#xff01;&#x1f618;&#x1f618;&#x1f618; &#x1f917;专栏&#xff1a;算法学习 &am…

多级缓存建设方案

项目背景 xx系统中对容量和耗时有较高要求&#xff0c;以支付优惠立减为例&#xff0c;每个用户咨询可用立减时&#xff0c;都会过一遍全量生效活动。目前日常活动数3000&#xff0c;目标2w&#xff1b;日常秒级咨询量1w&#xff0c;大促22w。所以如何支撑日常和大促的业务非常…

Unity利用UGUI RawImage组件制作转场动画

Unity利用UGUI RawImage组件制作转场动画 最近接到了一个unity全景图的小项目&#xff0c;由于在不同的场景之间转场时直接转会太过生硬&#xff0c;因此要求有个Alpha转场的动画。于是想到两种可行的方案&#xff1a; 一、UGUI方案 用UGUI显示当前屏幕纹理&#xff0c;然后…

python处理图像的各种技术镜像、旋转、遮挡、叠加、条带化

2.6 图像镜面对称 1、将图像水平镜面转换。 2、将图像垂直镜面转换。 import random #导入模块 import numpy as np import matplotlib.pyplot as plt a plt.imread("1.jpg") # 将图像沿着水平方向重复三次。 ba.copy() da.copy() # 将图像水平镜面转换。&…

【笔记】cuda大师班1-4

一.基本概念 进程&#xff08;process&#xff09;一个正在被执行的计算机程序的实例 上下文&#xff08;context&#xff09;&#xff1a;待处理数据的集合&#xff0c;允许处理器暂停&#xff0c;保持处理的执行和恢复处理 并发&#xff1a;上下文切换&#xff0c;主要应用于…

AIGC - 生产力新工具 Copilot

文章目录 介绍能干啥IDEA 安装 介绍 https://github.com/features/copilot 能干啥 Copilot的主要功能包括: 代码补全和提示:Copilot会根据上下文,智能提示您可能需要的变量,函数,参数等。快速生成代码:Copilot可以快速生成if语句,for循环,类定义,函数定义等代码模板。代码优…

Unity之OpenXR+XR Interaction Toolkit实现 传送

前言 VR中由于走动比较容易头晕&#xff0c;所以基本上玩家移动都是靠传送&#xff0c;这样用户更加直观&#xff0c;传送过去也不会感觉头晕。 好了&#xff0c;那么我们一起来说实现一下OpenXR的传送功能。 准备 我们新建一个3D&#xff08;URL&#xff09;项目&#xff0…

git 撤销add/commit,以及更换源命令

前言&#xff1a;主要是为了自己方便记录&#xff0c;省的每次都查找一下这些命令 1、当我们只是想撤回commit&#xff0c;保留add .的时候&#xff0c;可以用下方代码 git reset --soft HEAD^ 2、当我们想撤回commit以及add .的时候&#xff0c;可以用下方代码 git reset…

Mesh形变算法

前言&#xff1a; 作者正好因为动画、模拟仿真等等的重大需求需要预先研发离散形的模型Mesh的形变算法&#xff0c;并且要验证、研究适用的范围、特别是性能等等&#xff0c;摸着石头过河别喷&#xff0c;毕竟我主要是渲染、动画、引擎的对于计算几何、三维重建不是很熟悉&…