当前位置:网站首页>微服务:事务管理
微服务:事务管理
2022-08-01 08:31:00 【冯威】
作者:oec2003
公众号:不止dotNET
几乎所有的信息管理系统都会涉及到事务,事务的目的是为了保证数据的一致性,这里说的一致性是数据库状态的一致性。
说到数据库状态的一致性,相信大家都会想到 ACID :
原子性(Atomic):在一个事件的多个数据库操作中,要么同时成功,要么同时失败,例如:转账业务;
隔离性(Isolation):不同的业务之间处理数据相互独立,互不影响
持久性(Durability):正常提交的数据能够被持久化,不丢失数据,比如 mysql 天然就能持久化,redis 、 rabbitmq 也能通过设置进行持久化;
一致性(Consistency):最终的数据正确,所以说是通过 AID 这些手段来保证了 C 。
在单体架构中,通常是一套程序对应一个数据库,事务基于数据库本身的能力,如果你在 .NET Core 中使用 dapper 或 sqlsugar ,可以很容易进行事务的处理,可以参考下面文档:
https://dapper-tutorial.net/transaction https://www.donet5.com/Home/Doc?typeId=1183
但是,在微服务架构,分布式的场景中,事务的处理就会变得复杂,会存在多个节点,多个节点的同步、可用性等都是需要考虑的问题,在分布式中有一个著名的 CAP 理论:
C:数据一致性(Consisitency):分布式中存在多个节点,对某个指定的客户端来说,从任一节点读取数据保证能够获取到最新的写操作结果;
A:可用性(Acailability),非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)
P:分区容错性(Partition Tolerance),节点之间的数据传递是基于网络的,由于网络本身不是 100% 可靠,极端情况下会出现网络不可用的情况,进而将网络两端的节点分隔开来,这就是所谓的「网络分区」现象。在出现网络分区时,两部分的数据是不一致的,如果要保证数据的一致性,就必须要让没有及时同步数据的节点变为不可用,这就牺牲了可用性,否则就会牺牲一致性,所以在 P 一定存在的情况下,需要在 C 和 A 中间做取舍。
我们在 CAP、ACID 中讨论的一致性称为「强一致性」(Strong Consistency),而把牺牲了 C 的 AP 系统,但又要保证最终的结果的一致性,称为「弱一致性」,也叫最终一致性。最终一致性的概念由 eBay 的系统架构师丹 · 普利切特(Dan Pritchett)在 2008 年发表于 ACM 的论文「Base: An Acid Alternative」中提出的。
本文主要说下保证一致性的几种方式:TCC、SAGA 和消息队列。
TCC
TCC 是 Try-Confirm-Cancel 的缩写,分为了三个阶段:
Try:一个请求涉及到多个服务,多个服务会同时进行 Try,这个阶段为尝试执行阶段,在这个阶段中会进行数据的校验、检查,保障一致性,并准备资源,都成功会进入到 Confirm 阶段;
Confirm:确认执行阶段,不进行任何业务检查,多个服务的 Try 都执行成功了,多个服务都进入到 Confirm 阶段,在这个阶段直接使用 Try 阶段准备的资源来完成业务处理。注意,Confirm 阶段可能会重复执行,因此需要满足幂等性。
Cancel:如果在 Try 阶段有一个服务没有成功,那么所有的服务都进入到 Cancel 阶段,在该阶段,释放 Try 阶段预留的业务资源。注意,Cancel 阶段也可能会重复执行,因此也需要满足幂等性。
在 .NET Core 中可以参考:
https://github.com/simpleway2016/JMS
在 Java 中可以使用 seata:
https://github.com/seata/seata https://seata.io/zh-cn/
因为在 TCC 中的第一步 Try 需要预留资源,进行检查和校验,但在某些场景下,资源不是我们所能控制的,比如支付中,余额是银行管理的,我们通常没有权限。所以这时就不太适合 TCC ,可以考虑用 SAGA 来代替 TCC。
SAGA
SAGA 起源于 1987 年普林斯顿大学的赫克托 · 加西亚 · 莫利纳(Hector Garcia Molina)和肯尼斯 · 麦克米伦(Kenneth Salem)在 ACM 发表的一篇论文《SAGAS》。
SAGA 和 TCC 最大的区别是基于数据补偿机制来代替回滚。一个 SAGA 表示处理多个服务中数据的一系列操作,由一连串的本地事务组成,每个独立的本地事务中还是能够使用 ACID 。
SATA 由两部分组成:
将一个大的事务拆分成的若干个小的事务,比如一个大的事务 T ,拆分成 T1、T2、T3; 每一个子事务有对应的补偿动作,例如对应上面的 T1、T2、T3 有 C1、C2、C3 的补偿动作。
在 ACID 中如果出现异常,可以很容易进行回滚,但 SAGA 没办法自己回滚,不需依赖补偿动作来进行回滚。
如果 T1、T2、T3 都提交成功了,整个事务 T 就提交成功,如果执行 T2 时出现异常,这时有两种方式进行处理:
正向(不断重试):不断对 T2 进行重试操作,直到成功(不排除人工干预),等 T2 重试成功后,继续执行后面的 T3;
反向(补偿):T2 出现异常时,执行对应的补偿 C2,C2 必须执行成功(不排除人工),然后执行 T1 对应的补偿动作 C1 。
在上面提到的 seata 中也同样可以支持 SAGA 模式。
除了 seata ,还有一个用 go 语言写的 DTM 分布式事务框架也不错:
https://dtm.pub/ https://github.com/dtm-labs/dtm
而且,DTM 支持 C# 客户端:
https://github.com/dtm-labs/dtmcli-csharp
消息队列
消息队列相信大家都不陌生,我们零代码产品中调用外部接口的组件,会被用在一些复杂的业务逻辑编排中,对外部接口的调用就是使用消息队列,RabbitMQ 的延时队列加上死信队列可以来进行重试的操作。
还有另一种方式就是使用事务消息表,比如有这样一个场景,在系统列表中删除一条流程数据,这时需要做:
1、列表服务中对数据进行删除;
2、文件服务对这条数据相关的附件进行删除;
3、流程服务对该业务数据的所有流程信息进行删除。
具体的步骤如下:
1、列表服务删除数据成功后,在数据库中创建一张事务消息表,该表中记录事务 ID、数据删除成功的状态、业务数据 ID、附件待删除的状态、流程信息待删除的状态等;
2、列表服务删除数据成功后,发送消息分别进行附件删除处理和流程信息删除处理;
3、消息被正确处理后,修改事务消息表的状态;
4、创建一个单独的消息服务程序,轮询扫描事务消息表,如果发现状态没有变成已完成,就重新发送一个新的消息,这样附件删除和流程信息删除就会进行多次执行,这也要求这些操作必须是幂等的。
RabbitMQ 本身不支持分布式事务,不过有一些消息中间件是支持的,例如:RocketMQ,原生就支持分布式事务操作,可以更方便进行事务处理。
本文是一些理论的梳理,要想更彻底地掌握,可以选择一个框架,找几个场景,写写代码演练一下。
边栏推荐
- leetcode-6134:找到离给定两个节点最近的节点
- TiDB的真实数据库数据是存在kv和还是pd上?
- pytest接口自动化测试框架 | 跳过模块
- network basic learning
- 基于MySql,Redis,Mq,ES的高可用方案解析
- Chapters 6 and 7 of Huawei Deep Learning Course
- centos 安装php7.4,搭建hyperf,转发RDS
- [Beyond programming] When the fig leaf is lifted, when people begin to accept everything
- The socket option
- GO error handling
猜你喜欢
随机推荐
Ogg synchronizes oracle to mysql, there may be characters that need to be escaped in the field, how to configure escape?
Prime Ring Problem(素数环问题)
Mysql database deployment and initialization steps
数据分析6
【MySQL】操作表DML相关语句
UXDB如何返回当前数据库所有表的记录数?
pytest interface automation testing framework | parametrize source code analysis
Pytest | skip module interface test automation framework
MySQL查询进阶——从函数到表连接的使用你还记得吗
SAP ABAP ALV+SMARTFORS 表分页 报表打印程序
Flink SQL - client, how to deal with the source side and to increase the target, the SQL - client including mapping table and the JOB such as
Holoview--Introduction
云原生FAQ
LabVIEW RT中的用户界面更新速度
【数据集】各类绝缘子、鸟巢及防震锤数据集汇总
网络个各种协议
How to query database configuration parameters in GBase 8c, such as datestyle
flink sql-client,怎么处理源端与目标增加端,sql-client包括映射表与JOB如
【编程之外】当遮羞布被掀开,当人们开始接受一切
【手撕AHB-APB Bridge】~ AHB地址总线的低两位为什么不用来表示地址呢?