Java主流分布式解决方案多场景设计与实战|2023|同步更新中

无懈可击
• 阅读 126

Java主流分布式解决方案多场景设计与实战|2023|同步更新中

// 下栽の地止:http://www.shanxueit.com/2315/

事务 事务是应用程序中一系列严密的操作,所有操作必须成功完成,否则在每个操作中所作的所有更改都会被撤消。也就是事务具有原子性,一个事务中的一系列的操作要么全部成功,要么一个都不做。事务应该具有 4 个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为 ACID 特性。

分布式事务 分布式事务是指事务的参与者,支持事务的服务器,资源服务器以及事务管理器分别位于分布式系统的不同节点之上。通常一个分布式事务中会涉及对多个数据源或业务系统的操作。分布式事务也可以被定义为一种嵌套型的事务,同时也就具有了ACID事务的特性。

强一致性、弱一致性、最终一致性 强一致性

任何一次读都能读到某个数据的最近一次写的数据。系统中的所有进程,看到的操作顺序,都和全局时钟下的顺序一致。简言之,在任意时刻,所有节点中的数据是一样的。

弱一致性

数据更新后,如果能容忍后续的访问只能访问到部分或者全部访问不到,则是弱一致性。

最终一致性

不保证在任意时刻任意节点上的同一份数据都是相同的,但是随着时间的迁移,不同节点上的同一份数据总是在向趋同的方向变化。简单说,就是在一段时间后,节点间的数据会最终达到一致状态。

由于分布式事务方案,无法做到完全的ACID的保证,没有一种完美的方案,能够解决掉所有业务问题。因此在实际应用中,会根据业务的不同特性,选择最适合的分布式事务方案。

分布式事务的基础 CAP理论 Consistency(一致性):数据一致更新,所有数据变动都是同步的(强一致性)。

Availability(可用性):好的响应性能。

Partition tolerance(分区容错性) :可靠性。

定理:任何分布式系统只可同时满足二点,没法三者兼顾。

CA系统(放弃P):指将所有数据(或者仅仅是那些与事务相关的数据)都放在一个分布式节点上,就不会存在网络分区。所以强一致性以及可用性得到满足。

CP系统(放弃A):如果要求数据在各个服务器上是强一致的,然而网络分区会导致同步时间无限延长,那么如此一来可用性就得不到保障了。坚持事务ACID(原子性、一致性、隔离性和持久性)的传统数据库以及对结果一致性非常敏感的应用通常会做出这样的选择。

AP系统(放弃C):这里所说的放弃一致性,并不是完全放弃数据一致性,而是放弃数据的强一致性,而保留数据的最终一致性。如果即要求系统高可用又要求分区容错,那么就要放弃一致性了。因为一旦发生网络分区,节点之间将无法通信,为了满足高可用,每个节点只能用本地数据提供服务,这样就会导致数据不一致。一些遵守BASE原则数据库,(如:Cassandra、CouchDB等)往往会放宽对一致性的要求(满足最终一致性即可),一次来获取基本的可用性。

BASE理论 BASE 是 Basically Available(基本可用)、Soft state(软状态)和 Eventually consistent (最终一致性)三个短语的缩写。是对CAP中AP的一个扩展。

基本可用:分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。

软状态:允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是CAP中的不一致。

最终一致:最终一致是指经过一段时间后,所有节点数据都将会达到一致。

BASE解决了CAP中理论没有网络延迟,在BASE中用软状态和最终一致,保证了延迟后的一致性。BASE和 ACID 是相反的,它完全不同于ACID的强一致性模型,而是通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。

分布式事务解决方案 分布式事务的实现主要有以下 6 种方案:

2PC 方案

TCC 方案

本地消息表

MQ事务

Saga事务

最大努力通知方案

2PC方案 2PC方案分为两阶段:

第一阶段:事务管理器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交.

第二阶段:事务协调器要求每个数据库提交数据,或者回滚数据。

优点: 尽量保证了数据的强一致,实现成本较低,在各大主流数据库都有自己实现,对于MySQL是从5.5开始支持。

缺点:

单点问题:事务管理器在整个流程中扮演的角色很关键,如果其宕机,比如在第一阶段已经完成,在第二阶段正准备提交的时候事务管理器宕机,资源管理器就会一直阻塞,导致数据库无法使用。

同步阻塞:在准备就绪之后,资源管理器中的资源一直处于阻塞,直到提交完成,释放资源。

数据不一致:两阶段提交协议虽然为分布式数据强一致性所设计,但仍然存在数据不一致性的可能,比如在第二阶段中,假设协调者发出了事务commit的通知,但是因为网络问题该通知仅被一部分参与者所收到并执行了commit操作,其余的参与者则因为没有收到通知一直处于阻塞状态,这时候就产生了数据的不一致性。

总的来说,2PC方案比较简单,成本较低,但是其单点问题,以及不能支持高并发(由于同步阻塞)依然是其最大的弱点。

TCC TCC 的全称是:Try、Confirm、Cancel。

Try 阶段:这个阶段说的是对各个服务的资源做检测以及对资源进行 锁定或者预留。

Confirm 阶段:这个阶段说的是在各个服务中执行实际的操作。

Cancel 阶段:如果任何一个服务的业务方法执行出错,那么这里就需要 进行补偿,就是执行已经执行成功的业务逻辑的回滚操作。(把那些执行成功的回滚)

举个简单的例子如果你用100元买了一瓶水, Try阶段:你需要向你的钱包检查是否够100元并锁住这100元,水也是一样的。

如果有一个失败,则进行cancel(释放这100元和这一瓶水),如果cancel失败不论什么失败都进行重试cancel,所以需要保持幂等。

如果都成功,则进行confirm,确认这100元扣,和这一瓶水被卖,如果confirm失败无论什么失败则重试(会依靠活动日志进行重试)。

这种方案说实话几乎很少人使用,但是也有使用的场景。因为这个事务回滚实际上是严重依赖于你自己写代码来回滚和补偿了,会造成补偿代码巨大。

本地消息表 本地消息表的核心是将需要分布式处理的任务通过消息日志的方式来异步执行。消息日志可以存储到本地文本、数据库或消息队列,再通过业务规则自动或人工发起重试。人工重试更多的是应用于支付场景,通过对账系统对事后问题的处理。

对于本地消息队列来说核心是把大事务转变为小事务。还是举上面用100元去买一瓶水的例子。

1.当你扣钱的时候,你需要在你扣钱的服务器上新增加一个本地消息表,你需要把你扣钱和写入减去水的库存到本地消息表放入同一个事务(依靠数据库本地事务保证一致性。

2.这个时候有个定时任务去轮询这个本地事务表,把没有发送的消息,扔给商品库存服务器,叫他减去水的库存,到达商品服务器之后这个时候得先写入这个服务器的事务表,然后进行扣减,扣减成功后,更新事务表中的状态。

3.商品服务器通过定时任务扫描消息表或者直接通知扣钱服务器,扣钱服务器本地消息表进行状态更新。

4.针对一些异常情况,定时扫描未成功处理的消息,进行重新发送,在商品服务器接到消息之后,首先判断是否是重复的,如果已经接收,在判断是否执行,如果执行在马上又进行通知事务,如果未执行,需要重新执行需要由业务保证幂等,也就是不会多扣一瓶水。

本地消息队列是BASE理论,是最终一致模型,适用于对一致性要求不高的。实现这个模型时需要注意重试的幂等。

MQ事务 基于 MQ 的分布式事务方案其实是对本地消息表的封装,将本地消息表基于 MQ 内部,其他方面的协议基本与本地消息表一致。

MQ事务方案整体流程和本地消息表的流程很相似,如下图:

从上图可以看出和本地消息表方案唯一不同就是将本地消息表存在了MQ内部,而不是业务数据库中。

那么MQ内部的处理尤为重要,下面主要基于 RocketMQ 4.3 之后的版本介绍 MQ 的分布式事务方案。

在本地消息表方案中,保证事务主动方发写业务表数据和写消息表数据的一致性是基于数据库事务,RocketMQ 的事务消息相对于普通 MQ提供了 2PC 的提交接口,方案如下:

正常情况:事务主动方发消息

这种情况下,事务主动方服务正常,没有发生故障,发消息流程如下:

发送方向 MQ 服务端(MQ Server)发送 half 消息。

MQ Server 将消息持久化成功之后,向发送方 ack 确认消息已经发送成功。

发送方开始执行本地事务逻辑。

发送方根据本地事务执行结果向 MQ Server 提交二次确认(commit 或是 rollback)。

MQ Server 收到 commit 状态则将半消息标记为可投递,订阅方最终将收到该消息;MQ Server 收到 rollback 状态则删除半消息,订阅方将不会接受该消息。

异常情况:事务主动方消息恢复

在断网或者应用重启等异常情况下,图中 4 提交的二次确认超时未到达 MQ Server,此时处理逻辑如下:

MQ Server 对该消息发起消息回查。

发送方收到消息回查后,需要检查对应消息的本地事务执行的最终结果。

发送方根据检查得到的本地事务的最终状态再次提交二次确认。

MQ Server基于 commit/rollback 对消息进行投递或者删除。

优点

相比本地消息表方案,MQ 事务方案优点是:

消息数据独立存储 ,降低业务系统与消息系统之间的耦合。

吞吐量大于使用本地消息表方案。

缺点

一次消息发送需要两次网络请求(half 消息 + commit/rollback 消息) 。

业务处理服务需要实现消息状态回查接口。

Saga事务 Saga是由一系列的本地事务构成。每一个本地事务在更新完数据库之后,会发布一条消息或者一个事件来触发Saga中的下一个本地事务的执行。如果一个本地事务因为某些业务规则无法满足而失败,Saga会执行在这个失败的事务之前成功提交的所有事务的补偿操作。

Saga的实现有很多种方式,其中最流行的两种方式是:

基于事件的方式。这种方式没有协调中心,整个模式的工作方式就像舞蹈一样,各个舞蹈演员按照预先编排的动作和走位各自表演,最终形成一只舞蹈。处于当前Saga下的各个服务,会产生某类事件,或者监听其它服务产生的事件并决定是否需要针对监听到的事件做出响应。

基于命令的方式。这种方式的工作形式就像一只乐队,由一个指挥家(协调中心)来协调大家的工作。协调中心来告诉Saga的参与方应该执行哪一个本地事务。

最大努力通知方案 最大努力通知也称为定期校对,是对MQ事务方案的进一步优化。它在事务主动方增加了消息校对的接口,如果事务被动方没有接收到消息,此时可以调用事务主动方提供的消息校对的接口主动获取。

最大努力通知的整体流程如下图:

在可靠消息事务中,事务主动方需要将消息发送出去,并且消息接收方成功接收,这种可靠性发送是由事务主动方保证的;

但是最大努力通知,事务主动方尽最大努力(重试,轮询....)将事务发送给事务接收方,但是仍然存在消息接收不到,此时需要事务被动方主动调用事务主动方的消息校对接口查询业务消息并消费,这种通知的可靠性是由事务被动方保证的。

最大努力通知适用于业务通知类型,例如微信交易的结果,就是通过最大努力通知方式通知各个商户,既有回调通知,也有交易查询接口。

点赞
收藏
评论区
推荐文章
Easter79 Easter79
2年前
Spring事务(二):Spring事务的特点
事务特性实现事务必须满足以下四大特性:Atomicity(原子性):构成事务的的所有操作必须是一个逻辑单元,要么全部执行,要么全部不执行。Consistency(一致性):数据库在事务执行前后,完整性没有被破坏。(转账前后,钱的总数不变)Durability(持久性):事务执行成功后必须全部写入磁盘。
Wesley13 Wesley13
2年前
mysql 事物四大特性和事物的四个隔离
1、事物四大特性(ACID)1.原子性(atomicity):一个事务必须视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。2.一致性(consistency):数据库总数从一个一致性的状态转换到另一个一致性的状态。3.隔离性
Wesley13 Wesley13
2年前
MySql学习17
一.数据库事务的四大特性(ACID)如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性:原子性(Atomicity):原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,这和前面两篇博客介绍事务的功能是一样的概念,因此事务的操作如果成功就必须要完全应用到数据库,如果操
Wesley13 Wesley13
2年前
MySQL中的事务
MySQL中的事务为什么需要事务现在的软件基本上都是多用户、多程序、多线程的,对同一个表可能同时有很多人在用,为保持数据的一致性,所以提出了事务的概念。一个事务一般包含多个操作,这些操作必须当成一个整体来执行,要么都成功,要么都失败,不允许部分成功和部分失败。假如要从A的账户给B的账户转账1000元,那么A的账
Wesley13 Wesley13
2年前
MySQL transaction
MySQLtransaction(数据库的事务)数据库事务(DatabaseTransaction),是指作为单个逻辑工作单元执行的一系列操作。要么完全执行,要么完全地不执行。ACID事务必须具备ACID四个特性原子性(Atomicity)原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。一致性(Consistency)
Wesley13 Wesley13
2年前
MySql学习18
本篇讲述数据库中非常重要的事务概念和如何使用MySQL命令行窗口来进行数据库的事务操作。下一篇会讲述如何使用JDBC进行数据库的事务操作。  事务是指数据库中的一组逻辑操作,这个操作的特点就是在该组逻辑中,所有的操作要么全部成功,要么全部失败。在各个数据具有特别紧密的联系时,最好是使用数据库的事务来完成逻辑处理。  例如路人甲A给路人甲B转账
Wesley13 Wesley13
2年前
MySQL的四种事务隔离级别
本文实验的测试环境:Windows10cmdMySQL5.6.36InnoDB一、事务的基本要素(ACID)1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就
Wesley13 Wesley13
2年前
MySQL常见问题
事务四大特性原子性:不可分割的操作单元,事务中所有操作,要么全部成功;要么撤回到执行事务之前的状态一致性:如果在执行事务之前数据库是一致的,那么在执行事务之后数据库也还是一致的;隔离性:事务操作之间彼此独立和透明互不影响。事务独立运行。这通常使用锁来实现。一个事务处理后的结果,影响了其他事务,那么其他事务会撤回。
那年烟雨落申城 那年烟雨落申城
10个月前
事务的ACID,隔离级别,脏读,幻读和不可重复读
事务的ACID原子性(atomicity)一个事务中执行的sql语句,要么全部成功,要么全部失败,不可能一部分成功。一致性(consistency)事务执行前和执行后数据一致,也就是说事务中的sql语句不能只执行一部分。这种请款一般发生在事务异常中断,服
京东云开发者 京东云开发者
7个月前
浅谈分布式事务及解决方案 | 京东物流技术团队
1背景在讲述分布式事务的概念之前,我们先来回顾下事务相关的一些概念。1.1事务的基本概念就是一个程序执行单元,里面的操作要么全部执行成功,要么全部执行失败,不允许只成功一半另外一半执行失败的事情发生。例如一段事务代码做了两次数据库更新操作,那么这两次数据库