事务的概念

事务:
事务一般指的是逻辑上的一组操作,或者作为单个逻辑单元执行的一系列操作。同属于一个事务的操作会作为一个整体提交给系统,这些操作要么全部执行成功,要么全部执行失败。
数据库事务(维基百科):
数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
数据库事务通常包含了一个序列的对数据库的读/写操作。包含有以下两个目的:
为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。
当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。
当事务被提交给了数据库管理系统(DBMS),则DBMS需要确保该事务中的所有操作都成功完成且其结果被永久保存在数据库中,如果事务中有的操作没有成功完成,则事务中的所有操作都需要回滚,回到事务执行前的状态;同时,该事务对数据库或者其他事务的执行无影响,所有的事务都好像在独立的运行

ACID/CAP/BASE

ACID
1970 年詹姆斯 · 格雷(Jim Gray)提出了事务的 ACID 四大特性,将广义上的事务一致性具化到了原子性、一致性、隔离性和持久性这 4 个方面
原子性(Atomic):事务中的所有变更要么全部发生,要么一个也不发生。
一致性(Consistency):事务要保持数据的完整性。
隔离性(Isolation):多事务并行执行所得到的结果,与串行执行(一个接一个)完全相同。
持久性(Durability):一旦事务提交,它对数据的改变将被永久保留,不应受到任何系统故障的影响。
CAP
一致性(Consistency)
指强一致性,在写操作完成后开始的任何读操作都必须返回该值,或者后续写操作的结果。
也就是说,在一致性系统中,一旦客户端将值写入任何一台服务器并获得响应,那么之后client从其他任何服务器读取的都是刚写入的数据
一致性保证了不管向哪台服务器写入数据,其他的服务器能实时同步数据
可用性(Availability)
可用性(高可用)是指:每次向未崩溃的节点发送请求,总能保证收到响应数据(允许不是最新数据)
分区容忍性(Partition tolerance)
分布式系统在遇到任何网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务,也就是说,服务器A 和B 发送给对方的任何消息都是可以放弃的,也就是说A和B可能因为各种意外情况,导致无法成功进行同步,分布式系统要能容忍这种情况。除非整个网络环境都发生了故障
BASE
BASE 代表了三个特性,BA 表示基本可用性(Basically Available),S 表示软状态(Soft State),E 表示最终一致性(Eventual Consistency):
基本可用性,是指某些部分出现故障,那么系统的其余部分依然可用。
软状态或柔性事务,是指数据处理过程中,存在数据状态暂时不一致的情况,但最终会实现事务的一致性。
最终一致性,是指单数据项的多副本,经过一段时间,最终达成一致。
ACID 是数据库事务完整性的理论,CAP 是分布式系统设计理论,BASE 是 CAP 理论中 AP 方案的延伸

什么是一致性?(Consistency)

一直以来,在“分布式系统”和“数据库”这两个学科中,一致性(Consistency)都是重要概念,但它表达的内容却并不相同。
对于分布式系统而言,一致性是在探讨当系统内的一份逻辑数据存在多个物理的数据副本时,对其执行读写操作会产生什么样的结果,这也符合 CAP 理论对一致性的表述。
而在数据库领域,“一致性”与事务密切相关,又进一步细化到 ACID 四个方面。其中,I 所代表的隔离性(Isolation),是“一致性”的核心内容,研究的就是如何协调事务之间的冲突。

数据库对事务(ACID)的支持

数据库对一致性的zzhzhizhi’czhi’chzhi’chi支持
隔离性与异常

微服务时代的事务处理原则

假定网络或者服务不可靠

将全局事务建模成一组本地ACID事务

引入事务补偿机制

处理失败场景事务始终处在一种明确的状态(不管成功还是失败)

最终一致

考虑隔离性

考虑幂等性

异步响应式,尽量避免直接同步调用

常用解决方案

DTP/2PC/3PC
TCC
本地消息表
可靠消息事务
最大努力通知
SAGA

2PC

2pc基本流程

2PC的问题

同步阻塞
同步阻塞执行过程中,数据库要锁定对应的数据行。如果其他事务刚好也要操作这些数据行,那它们就只能等待。其实同步阻塞只是设计方式,真正的问题在于这种设计会导致分布式事务出现高延迟和性能的显著下降。
单点故障
单点故障事务管理器非常重要,一旦发生故障,数据库会一直阻塞下去。尤其是在第二阶段发生故障的话,所有数据库还都处于锁定事务资源的状态中,从而无法继续完成事务操作。
数据不一致
数据不一致在第二阶段,当事务管理器向参与者发送 Commit 请求之后,发生了局部网络异常,导致只有部分数据库接收到请求,但是其他数据库未接到请求所以无法提交事务,整个系统就会出现数据不一致性的现象。
无法解决的问题
如果在第二阶段事务管理器发出commit消息后宕机,并且唯一接收到这条commit消息的资源管理器也宕机了,则无法确认这条事务无法提交

TCC

Try:尝试执行阶段,完成所有业务可执行性的检查(保障一致性),并且预留好事务需要用到的所有业务资源(保障隔离性)。
Confirm:确认执行阶段,不进行任何业务检查,直接使用 Try 阶段准备的资源来完成业务处理。注意,Confirm 阶段可能会重复执行,因此需要满足幂等性。
Cancel:取消执行阶段,释放 Try 阶段预留的业务资源。注意,Cancel 阶段也可能会重复执行,因此也需要满足幂等性。

SAGA

把大事务拆分成若干个小事务,将整个分布式事务 T 分解为 n 个子事务。每个子事务都应该、或者能被看作是原子行为。如果分布式事务 T 能够正常提交,那么它对数据的影响(最终一致性)就应该与连续按顺序成功提交子事务 Ti 等价。

每一个子事务设计对应的补偿动作。Ti 与 Ci 必须满足以下条件:Ti 与 Ci 都具备幂等性;Ti 与 Ci 满足交换律(Commutative),即不管是先执行 Ti 还是先执行 Ci,效果都是一样的;Ci 必须能成功提交,即不考虑 Ci 本身提交失败被回滚的情况,如果出现就必须持续重试直至成功,或者要人工介入

正向恢复(Forward Recovery):如果 Ti 事务提交失败,则一直对 Ti 进行重试,直至成功为止(最大努力交付)。这种恢复方式不需要补偿,适用于事务最终都要成功的场景。正向恢复的执行模式为:T1,T2,…,Ti(失败),Ti(重试)…,Ti+1,…,Tn

反向恢复(Backward Recovery):如果 Ti 事务提交失败,则一直执行 Ci 对 Ti 进行补偿,直至成功为止(最大努力交付)。这里要求 Ci 必须(在持续重试后)执行成功。反向恢复的执行模式为:T1,T2,…,Ti(失败),Ci(补偿),…,C2,C1

本地消息表

  • 事务发起发将业务数据和消息数据作为一个本地事务写入本地数据库中
  • 使用专门的定时任务将本地消息表中的消息写入消息中间件,如果写入成功将消息从本地消息表删除。否则根据一定的规则重试操作
  • 如果消息根据一定的规则写入消息中间件仍然失败,可将失败的消息数据转储到死信队列,后续人工干预
  • 事务参与方订阅消息中间件的消息,当接收到消息中间件的消息时,完成本地的业务逻辑
  • 事务参与方本地事务执行成功,整个分布式事务成功。否则会根据一定的规则进行重试。如果仍然不能成功执行本地事务,会给事务发起发一条事务执行失败的消息,以此通知事务发起方进行事务回滚

事务消息(RocketMQ)

以上流程主要部分在RocketMQ自动实现了,开发者需要实现本地事务的执行逻辑和本地事务的回查方法
https://github.com/apache/rocketmq/blob/master/docs/cn/design.md

常见开源实现

SEATA

  • Transaction Coordinator(TC): Maintain status of global and branch transactions, drive the global commit or rollback.
  • Transaction Manager(TM): Define the scope of global transaction: begin a global transaction, commit or rollback a global transaction.
  • Resource Manager(RM): Manage resources that branch transactions working on, talk to TC for registering branch transactions and reporting status of branch transactions, and drive the branch transaction commit or rollback.
  • TM asks TC to begin a new global transaction. TC generates an XID representing the global transaction.
  • XID is propagated through microservices’ invoke chain.
  • RM registers local transaction as a branch of the corresponding global transaction of XID to TC.
  • TM asks TC for committing or rollbacking the corresponding global transaction of XID.
  • TC drives all branch transactions under the corresponding global transaction of XID to finish branch committing or rollbacking.

https://github.com/seata/seata-samples/blob/master/tcc/springboot-tcc-sample/src/main/java/io/seata/samples/tcc/springboot/

hmily

TCC
TAC

https://github.com/dromara/distribute-transaction/blob/master/

Cadence

Cadence is a distributed, scalable, durable, and highly available orchestration engine to execute asynchronous long-running business logic in a scalable and resilient way.

https://github.com/uber/cadence-java-samples/blob/master/src/main/java/com/uber/cadence/samples/bookingsaga/