【分布式】万字图文解析——深入七大分布式事务解决方案
分布式事务
分布式事务是指跨多个独立服务或系统的事务管理,以确保这些服务中的数据变更要么全部成功,要么全部回滚,从而保证数据的一致性。在微服务架构和分布式系统中,由于业务逻辑往往会跨多个服务,传统的单体事务无法覆盖,因此需要通过分布式事务来保障一致性。
三种数据一致性模型:
- 强一致性:系统保证每个读操作都将返回最近的写操作的结果,即任何时间点,客户端都将看到相同的数据视图。
- 弱一致性:放宽了一致性保证,允许在不同节点之间的数据访问之间存在一定程度的不一致性,以换取更高的性能和可用性。
- 最终一致性:允许在系统发生分区或网络故障后,经过一段时间,系统将最终达到一致状态。
刚性事务
刚性事务(Rigid Transaction)也称为强一致性事务,遵循严格的ACID特性(原子性、一致性、隔离性、持久性),确保所有操作都严格按照要求执行,要么全部成功,要么全部回滚。刚性事务常用于金融系统、银行转账等场景,要求数据高度一致,不能有任何误差。
在分布式系统中,实现刚性事务通常采用2PC或3PC协议,但这些协议会带来较高的性能开销,同时存在同步阻塞等问题。因此,刚性事务适合对数据一致性要求极高、但允许较高事务延迟的场景。
2PC或3PC协议根据 XA
规范衍生而来,XA
规范将分布式事务处理模型中涉及到了角色主要分为了应用程序(AP)、事务管理器(TM)和资源管理器(RM)
AP(Application Program)
:应用程序本身。RM(Resource Manager)
:资源管理器,也就是事务的参与者,绝大部分情况下就是指数据库,一个分布式事务往往涉及到多个资源管理器。TM(Transaction Manager)
:事务管理器,负责管理全局事务,分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚、失败恢复等。
两阶段提交
2PC(Two-Phase Commit Protocol,两阶段提交协议)是分布式系统中广泛使用的一种协议,用于保证事务跨多个节点(参与者)一致地提交或回滚。
两阶段提交协议分为两个阶段:准备阶段和提交阶段。
准备阶段
- 事务管理器(TM) 向所有事务参与者(资源管理器,RM) 发送 准备提交(prepare) 的请求。
- 每个事务参与者在收到请求后执行以下操作:
- 执行本地数据库事务预操作,比如写
redo log / undo log
日志,保留修改(如将数据写入暂存区域或进行日志记录),但不提交。 - 若该操作能够成功完成并保证后续提交,则返回同意消息。
- 若遇到错误或不能确保事务提交成功,则返回拒绝消息。
- 执行本地数据库事务预操作,比如写
- 在准备阶段,事务参与者只是准备提交,尚未实际提交事务。这使得系统仍然处于一致性状态。

提交阶段
- 如果所有事务参与者都返回了同意消息,事务管理器向所有参与者发送提交(Commit)请求。
- 各参与者收到提交消息后,正式提交事务操作,释放锁,清除临时数据,并通知事务管理器提交成功。
- 如果任何一个事务参与者返回拒绝消息,事务管理器向所有参与者发送回滚(Rollback)请求。
- 各参与者收到回滚消息后,撤销预操作,将状态恢复到事务开始之前。
- 在提交阶段,如果某个参与者出现故障,事务管理器会根据超时或故障检测机制来决定事务状态,尽量使所有节点最终保持一致。

存在的问题
- 同步阻塞:在事务提交的过程中,如果事务管理者出现故障,所有的事务参与者会进入阻塞状态,等待事务管理者的进一步指令,导致整个系统的事务处理停滞,不能继续执行其他事务。
- 单点故障:事务管理器是单点故障,如果事务管理器在提交阶段崩溃,系统将无法知道事务的最终状态,容易导致数据不一致。
- 数据不一致风险:在提交阶段,若事务管理器在发送提交或回滚请求后崩溃,可能导致部分参与者收到提交请求,而部分未收到,从而造成数据不一致。
三阶段提交
3PC(Three-Phase Commit Protocol,三阶段提交协议)是在两阶段提交协议的基础上进一步改进的分布式事务一致性协议,通过增加预提交阶段,增强了系统的容错能力和处理网络分区的能力,以解决2PC的同步阻塞问题和单点故障风险。
准备阶段
- 事务管理器(TM) 向所有事务参与者(资源管理器,RM) 发送「准备请求」,询问它们是否能够完成事务提交操作。
- 每个事务参与者收到「准备请求」后,如果认为自己可以完成事务,则返回同意消息;如果认为无法完成,则返回拒绝消息。
- 事务管理器收集所有参与者的响应:
- 若所有事务参与者都返回同意消息,则进入预提交阶段。
- 若任何一个事务参与者返回拒绝消息,则进入终止阶段并通知所有参与者回滚事务。

预提交阶段
- 如果所有事务参与者在第一阶段都返回了同意消息,事务管理器向所有参与者发送「预提交请求」。
- 每个事务参与者收到「预提交请求」后,执行本地数据库事务预操作,记录日志,保存即将提交的事务信息,以确保即使事务管理器故障也能恢复状态。如果事务参与者成功执行了事务预操作,发送预提交成功给事务管理器;如果执行失败,返回预提交失败给事务管理器。
- 预提交阶段通过提前记录事务信息,保证即使事务管理器故障,事务参与者也能够通过日志记录自我恢复。
- 事务管理器在等待一段时间后收集所有参与者的响应:
- 若所有参与者都返回预提交成功,事务管理器进入提交阶段。
- 若任意一个参与者返回预提交失败,则事务管理器进入终止阶段并通知所有参与者回滚事务。

提交阶段
- 若事务管理器在预提交阶段收到所有参与者的预提交成功,则向所有参与者发送「事务提交请求」。
- 各参与者收到提交请求后,正式提交事务操作,释放锁,清除临时数据,并返回提交完成。
- 若事务管理器在预提交阶段未收到所有参与者的响应,或检测到参与者或事务管理器自身出现故障,则事务管理器向所有参与者发送「事务回滚请求」。
- 各参与者收到回滚请求后,撤销事务,并返回回滚完成。

优缺点
虽然 3PC 通过引入超时机制和预提交阶段一定程度上解决了 2PC 的同步阻塞和单点故障的问题,但是依然存在数据不一致的问题,同时也引入了一些新问题比如性能糟糕。
- 解决同步阻塞:在3PC中,通过预提交阶段参与者在实际提交前达成共识状态,具备了超时控制和独立决策的条件。即使协调者故障,参与者也能在超时后依据自身状态决定提交或回滚,从而有效避免了因协调者故障导致的长时间同步阻塞问题。
- 解决单点故障:在3PC中,事务参与者引入了超时机制,当事务管理者挂掉后,事务参与者在等待超时后可以根据自身的状态来进行决策(如提交或回滚),不必依赖事务管理者的指令,从而降低了事务管理者的单点故障风险。
存在的问题:
- 网络分区风险:3PC试图通过在预提交阶段前引入准备阶段来减少阻塞问题,但如果在该阶段发生网络分区,事务管理器和参与者之间的通信可能会断开。此时,部分参与者可能会继续提交事务,而其他未收到指令的参与者则可能回滚,从而导致数据不一致。
- 性能降低:3PC虽然解决了一些2PC的阻塞问题,但增加的确认阶段和处理步骤使得事务处理的整体延迟变高。在高并发环境下,系统性能和响应速度可能会受到影响,导致事务处理效率较低。
- 数据不一致风险:虽然3PC引入了超时机制,但当事务管理器在预提交阶段(准备提交)崩溃且没有及时恢复时,参与者可能会依据超时策略决定提交或回滚,导致不同参与者采取了不同的事务状态,从而产生数据不一致。
柔性事务
柔性事务(Flexible Transaction)也称为最终一致性事务,放宽了对事务的严格性要求,允许系统在短期内出现不一致,只要在一段时间后达成最终一致性即可。柔性事务通常不完全遵循ACID特性,而采用BASE理论(基本可用、软状态、最终一致),在保证系统可用性的同时降低了对一致性的强制要求。
柔性事务广泛应用于电商订单处理、社交应用等对实时性和高可用性要求高,但数据一致性可延迟的场景。
柔性事务常见的实现方式包括:
- TCC(Try-Confirm-Cancel):将事务分解为三个步骤,先尝试(Try),再确认(Confirm)或取消(Cancel)。
- 可靠消息事务:利用消息队列确保最终一致性,通过消息重试机制来保证事务操作的最终完成。
- 补偿事务:通过补偿机制在出现错误时对事务进行回滚。
TCC
TCC(Try-Confirm-Cancel)是一种分布式事务解决方案,特别适用于柔性事务场景。TCC通过将事务分解为三个步骤来确保最终一致性,提供对事务操作的更加灵活的控制。
执行流程
- Try(尝试)阶段:事务参与者尝试执行本地事务,并对全局事务预留业务资源。如果
try
阶段执行成功,参与者会返回一个成功标识,否则会返回一个失败标识。 - Confirm(确认)阶段:如果所有参与者的
try
阶段都执行成功,则协调者通知所有参与者提交事务,执行confirm
阶段。这时参与者将在本地提交事务,并处理全局事务预留的资源。 - Cancel(取消)阶段:如果任意参与者在
try
阶段或Confirm
阶段执行失败,则协调者通知所有参与者回滚事务,执行cancel
阶段。这时参与者将释放预留的业务资源。

如果Confirm或者Cancel执行失败,可以采用重试的方式减少因为网络问题导致TM没有接收到消息的情况,此外,还可以采用异常监控、日志记录和人工干预的方式来保证事务的一致性。
对于Confirm执行失败,还可以采用执行Cancel操作的方式,撤销在Try阶段预留的事务资源。
典型示例
假设我们有一个转账服务,需要从 A 账户转账 100 元到 B 账户,同时从 A 账户转账 200 元到 C 账户,总计从 A 账户中扣减 300 元。整个事务流程分为 Try、Confirm 和 Cancel 三个阶段:
- Try 阶段:转账服务首先冻结 A 账户的 300 元,以确保后续转账的可用性和一致性。
- Confirm 阶段:如果所有 Try 操作都成功执行,转账服务进入 Confirm 阶段,实际执行转账操作。此时,A 账户的冻结金额解冻,系统将 100 元转入 B 账户,200 元转入 C 账户,完成资金划转。
- Cancel 阶段:如果在 Try 阶段某一步失败,则系统进入 Cancel 阶段,对 A 账户的冻结金额进行解冻处理,保证资金不受影响;如果 Confirm 阶段中某步转账失败,例如 A 到 B 的转账失败,而 A 到 C 的转账已完成,则需要通过 C 到 A 的逆向转账操作将金额退回,保证 A 账户资金最终一致。
通过这种方式,TCC 模式确保了分布式事务的最终一致性,即使在部分失败的情况下,系统也能通过回滚或补偿机制恢复到一致状态。
存在的问题
- 空回滚:在TCC协议中,如果某些参与者在Try阶段成功,而其他参与者失败,此时所有参与者需要执行Cancel操作。对于那些在Try阶段没有成功的参与者来说,执行Cancel操作就成为一次空回滚。如果业务没有有效地识别和处理空回滚,可能会导致异常错误,甚至可能导致Cancel一直失败,最终使整个分布式事务失败。
- 悬挂事务:在TCC执行一阶段的Try操作阶段时,可能出现网络拥堵导致超时,事务协调器会触发二阶段的Cancel操作。而下游的节点由于网络延迟先接收到了Cancel,网络恢复后会在Cancel后再次接收到Try请求,这就导致该节点Try操作占用的资源无法释放,造成事务悬挂。
解决方案
通过引入分布式事务记录表,可以解决上述两个问题。该表中两个关键字段,一个是 tx_id
字段用于保存本次处理的事务ID,另一个是 state
字段用于记录本次事务的执行状态。
当后续在进行Try、Confirm和Cancel操作时,都需要在本地事务中创建或修改这条记录。
CREATE TABLE 'distribute_transaction' ('tx_id' varchar(128) NOT NULL COMMENT '事务id','state' int(1) DEFAULT NULL COMMENT '事务状态,0:try,1:confirm,2:cancel',PRIMARY KEY ('tx_id')
)
- 解决空回滚:当一个事务参与者接受到Cancel请求时,先去事务记录表中查询是否存在当前事务
trx_id
的Try操作的记录,如果记录不存在,则说明Try操作并未成功,此时可以直接跳过Cancel,避免执行空回滚。 - 解决悬挂事务:当一个事务参与者接收到Try请求时,先去事务记录表中查询是否存在当前事务
trx_id
的Cancel操作的记录,如果存在,说明执行Try操作会导致事务悬挂,无法释放资源,拒绝本次Try请求。
MQ事务消息
RocketMQ 事务消息是一种可靠的消息传输机制,用于保证分布式事务的最终一致性。事务消息允许将消息的发送与本地事务绑定在一起,使得即使在网络异常或系统故障情况下,消息也能最终达到一致状态。
执行流程
下图为MQ事务消息的总体执行流程:
RocketMQ 的事务消息通过 TransactionListener
接口实现,其执行流程总体上可以分为四个步骤:
- 发送半消息:消息发送方给
MQ Broker
发送一条Half
消息,即半消息。半消息会存储在Broker
的事务消息日志中,且该半消息暂时无法被消费。 - 执行本地事务:半消息发送成功后,
Broker
会通知消息发送方执行本地事务,消息发送方可以根据本地事务的执行情况,判断是否需要提交该事务消息。 - 发送提交或回滚消息:如果本地事务执行成功,发送方会通知
Broker
提交该事务消息,使得消息被消费者消费;如果本地事务执行失败,发送方会通知Broker
回滚该事务消息,并将该半消息从事务消息日志中删除,不会被消费者消费。 - 回查事务状态:如果
Broker
在规定时间内没有收到COMMIT
和ROLLBACK
消息,会向消息发送方发送一个回查请求,根据请求的回调结果判断是否需要提交或回滚事务消息。
相关问题
半消息发送失败了,如何处理?
在 RocketMQ 事务消息的一致性解决方案中,应用程序(即消息发送方)是先发送半消息,后执行的本地事务。因此如果半消息发送失败了,直接进行消息重发即可,不会造成数据不一致的问题。
为什么需要先发送半消息?
主要原因是:本地事务执行完成后再发送消息,如果消息发送失败,那么 Broker
将无法感知本地事务的执行状态。
如果先执行完本地事务消息,再发送消息,当发送消息失败时,消费者没有半消息提供的本地事务的任何信息,因此 Broker
无法去回查本地事务的状态。
通过先发送半消息,Broker
可以在日志中记录该半消息,进而获知该事务的“初步状态”。如果半消息在超时内没有完成提交或回滚,Broker
就可以发起回查,以此来确保事务消息的最终一致性。因此,半消息为 Broker
提供了识别和查询特定事务状态的依据。
本地消息表
本地消息表(Local Message Table)同样也是一种分布式系统中常用的可靠消息传递方案。其核心思想是在发送消息的业务系统中,在消息发送方创建一个本地消息表,用于记录每一条需要发送的消息,并通过定时任务确保消息的可靠传递。
执行流程
一个典型的本地消息表结构如下:
字段 | 类型 | 说明 |
---|---|---|
id | VARCHAR(36) | 消息ID,唯一标识 |
content | TEXT | 消息内容 |
status | INT | 消息状态(0: 待发送,1: 已发送,2: 已完成) |
retry_count | INT | 重试次数 |
create_time | TIMESTAMP | 创建时间 |
update_time | TIMESTAMP | 最后更新时间 |
该方案主要将分布式事务拆分成了本地事务和消息事务两个部分,具体执行流程如下:
- 执行本地事务:首先由消息发送方开启本地事务,在本地事务中执行具体的业务操作。业务操作执行成功后,发送方将需要通知到其他服务的消息记录在本地消息表中,并设置消息状态为 「待发送」。
- 定时任务发送消息:在本地消息表中,消息初始状态为 「待发送」 。业务系统通过定时任务周期性地扫描本地消息表,找到所有 「待发送」 状态的消息,将其发送到消息队列,并将状态设置为 「已发送」。定时任务的时间间隔可以根据业务需求设置。
- 保证消息一致性:消息发送到消息队列后,可以通过消息重试机制,防止因网络问题导致传递的消息丢失问题;消息传递到消费者后,可以通过消费者确认机制、消息幂等处理来保证消息的一致性。
- 返回消费结果:消费者消费完毕后,返回消费结果给生产者。生产者接收到消费者的消费确认后,根据消息的唯一ID,将本地消息表中对应消息的状态更新为 「已完成」。
相关问题
如果步骤1和2失败,如何处理?
当本地事务执行失败时,由于此阶段将业务操作和消息表写入放在了同一个事务中,即使步骤1和2执行失败,事务也可以通过回滚恢复数据,保证业务操作和消息表写入的一致性。
如果步骤3中的消息发送失败,如何处理?
需要在消息发送方开启一个定时任务,不断的扫描本地消息表中状态为 「待发送」 的消息,对于未发送成功的消息重新投递。
如果步骤4和5失败,如何处理?
依靠消费者的确认机制和重试机制,如果消息丢失或者处理失败,则重新进行投递。此外,还可以借助死信队列进行额外处理。
如果步骤6和7失败,即本地消息表更新失败,如何处理?
执行到这里时,已经可以保证消息发送方和消息接收方的业务数据保持一致了,但是本地消息表的数据还未更新。消息接收方可以设置定时任务,定期扫描本地消息表中的消息,如果消息为 「已发送」 而不是 「已完成」,可以通过重试来再次尝试更新本地消息的状态。此外,消息发送方可以设置定时任务,主动查询消费者的业务状态,如果消息被正常消费,可以直接更新本地消息表。
Saga
Saga 是一种分布式事务管理模式,主要用于解决微服务架构中跨多个服务的事务一致性问题。Saga模式通过将一个大事务分解成一系列小的局部事务,并通过补偿机制来保证最终一致性,从而避免了传统的分布式事务(如2PC或3PC)带来的性能瓶颈和复杂性。
协调式
编排式Saga是由一个中央协调者来控制整个Saga事务的执行流程。协调者负责决定每个局部事务的执行顺序,处理每个局部事务的成功或失败,并在必要时触发补偿操作。

编排式
编排式没有中央协调者,而是通过事件驱动的方式来协调各个局部事务的执行。每个服务通过发布事件来通知其他服务,其他服务根据事件决定是否执行后续操作或进行补偿。

对比
编排式Saga适用于事务流程较为清晰、需要集中控制的场景,尤其是在业务流程复杂且需要监控和调度时。它具有较强的控制能力,但可能会带来单点故障问题。
事件驱动式Saga适用于高可扩展性、去中心化的分布式系统,适合松耦合的微服务架构。它更加灵活,但在实现上需要处理更复杂的事件和状态管理。
特性 | 编排式(Orchestration) | 事件驱动式(Choreography) |
---|---|---|
控制方式 | 中央协调者控制事务执行 | 各个服务通过事件进行事务协作 |
事务执行顺序 | 顺序执行,协调者决定后续事务的执行 | 各个服务根据事件决定执行顺序 |
补偿操作 | 由协调者决定是否进行补偿操作 | 由各服务根据事件决定补偿操作 |
扩展性 | 较差,协调者可能成为瓶颈 | 高,服务间解耦,易于扩展 |
耦合度 | 高,服务需要与协调者交互 | 低,服务间解耦,事件驱动 |
单点故障问题 | 是,协调者故障会影响整个事务 | 否,没有单点故障问题 |
监控与调试 | 相对简单,所有操作由协调者管理 | 较为复杂,需要事件追踪和状态管理 |
最大努力通知
在最大努力通知机制中,发送方会尽最大可能确保通知送达目标,通常通过重试机制提高通知的到达率。在此过程中,若出现网络通信故障或消息队列异常,就可能导致消息传递失败,即消息可能会丢失。因此,最大努力通知机制不能完全保证接收方一定能收到每条消息,但会尽最大努力确保消息通知的完成。
最大努力通知常见实现:生产者重试机制、消费者重试机制、死信队列、定时任务重试
最大努力通知适合在以下场景中使用:
- 日志记录:日志记录的发送可以采用最大努力通知的方式,保证不影响主业务流程。
- 非核心业务流程:例如积分更新、通知消息推送等,在用户体验上容错性较高的场景。
事务对比
TCC和2PC/3PC
适用场景:
- TCC:提供最终一致性,允许短时间内的数据不一致,通过补偿机制在失败后恢复状态。适合对响应速度要求高、允许一定延迟一致性的场景,如电商订单处理、支付等需要预留资源的业务。
- 2PC:提供强一致性,确保所有参与者最终的状态保持一致,要么全部成功提交,要么全部回滚。适合对一致性要求高的场景,如金融系统、银行转账等场景,要求数据高度一致,不能有任何误差。
执行流程:
- TCC:三阶段模型,主要包括Try(预留资源)、Confirm(提交)、Cancel(补偿/撤销),在Try或Confirm阶段执行失败可以进行Cancel补偿。
- 2PC:两阶段模型,主要包括Prepare(准备)和Commit(提交),无独立的回滚机制。
容错和恢复机制:
- TCC:每个阶段都有独立的失败处理,通过Cancel阶段的补偿操作可以回滚已预留的资源。
- 2PC:容错能力较弱,尤其在协调者宕机的情况下易发生资源锁死,恢复依赖协调者的重启和日志记录。
实现方式:
- TCC:是业务层面的分布式事务,不会一直持有资源的锁,性能较好。TCC 方案允许各个参与者自定义Try、Confirm和Cancel事务逻辑,对业务侵入性较高,但具有较好的灵活性和可恢复性。
- 2PC:是资源层面的分布式事务,需要数据库支持XA协议,在两阶段提交的整个过程中,会一直持有资源的锁,一般高并发性能会比较差。2PC 方案由协调者统一管理事务状态,能确保强一致性,但在分布式系统中较为耗时,且在网络中断或协调者失败时可能会出现阻塞问题。
特点 | TCC | 2PC |
---|---|---|
事务管理 | 由业务逻辑分阶段管理 | 由协调者统一管理 |
阶段划分 | Try、Confirm、Cancel | 准备阶段、提交阶段 |
执行方式 | 预留资源+确认/取消业务执行 | 准备阶段锁定资源+正式提交/回滚 |
一致性 | 最终一致性 | 强一致性 |
资源锁定时间 | 较短 | 较长,可能导致阻塞 |
容错机制 | 允许自定义重试和补偿 | 协调者故障会阻塞事务 |
性能 | 较高,灵活性好 | 较低,且有单点故障风险 |
MQ事务消息&本地消息表&最大努力通知
适用场景:
- MQ事务消息:适用于金融交易、订单支付等场景,尤其适合对系统一致性和事务可靠性要求较高的场景。事务消息能确保在消息发送和本地事务之间的一致性。
- 本地消息表:适用于异步处理或延迟处理,尤其是在高并发、大流量场景中,可以通过本地消息表和定时任务确保消息可靠性。
- 最大努力通知:适用于容忍一定消息丢失的场景,例如日志记录、通知推送等业务,这类业务的容错性较高,不需要完全保证每条消息的送达,只要尽最大努力确保通知的到达即可。
执行流程:
- MQ事务消息:消息发送方先发送半消息到
Broker
,此时消息不可消费,但Broker
会记录该消息状态。接着执行本地事务,根据执行结果,发送方通知Broker
提交或回滚消息,决定消息是否可消费。如果Broker
在规定时间内未收到确认,会向发送方发起回查请求,以确保消息状态和事务最终一致。 - 本地消息表:发送方在本地事务中记录消息到本地消息表,确保消息与业务操作同步执行且一致。记录的消息状态为“待发送”,定时任务定期扫描表中待发送的消息,将其发送至消息队列。消息成功消费后,消费者通过确认机制通知发送方,发送方将消息状态更新为“已完成”。
- 最大努力通知:发送方在消息发送过程中尽量保证消息成功传递给接收方,即使遇到网络问题也会进行多次重试。发送失败的消息会进入重试队列或死信队列,以便后续重发或进一步处理。尽管此机制不能保证百分百的消息送达,但通过多层次的重试和降级措施,努力减少消息丢失。
容错和恢复机制:
- MQ事务消息:消息发送方先发送半消息到
Broker
并记录状态,接着执行本地事务。根据事务结果决定提交或回滚该消息;如果Broker
未收到确认,将回查事务状态,确保消息最终一致性。 - 本地消息表:本地事务中将消息记录到本地消息表并设为“待发送”,由定时任务扫描发送至消息队列。消息消费成功后更新状态为“已完成”,保证业务和消息的最终一致。
- 最大努力通知:发送方通过多次重试确保消息尽量传递成功,遇到异常则进入重试或死信队列处理。尽管不能确保百分百送达,通过重试和降级机制尽量减少消息丢失。
性能与复杂度:
- MQ事务消息:性能较低,因为每次发送消息都需要和本地事务进行绑定,并且涉及到消息提交或回滚的操作。系统复杂度较高,需要处理回查等操作。
- 本地消息表:性能相对较好,通过定时任务和本地消息表机制,不需要等待事务的回查,但需要额外的定时任务和表管理,且数据库的存储压力较大。
- 最大努力通知:性能最好,消息的发送与本地事务并不绑定,只需要通过重试机制和死信队列保证尽最大努力将消息送达。适用于容忍一定丢失的业务场景。
特点 | MQ事务消息 | 本地消息表 | 最大努力通知 |
---|---|---|---|
适用场景 | 需要保证分布式事务一致性的场景 | 不要求强一致性,确保消息最终送达 | 容忍一定消息丢失的场景 |
执行流程 | 发送半消息 -> 执行本地事务 -> 提交/回滚消息 -> 回查事务状态 | 执行本地事务 -> 记录消息 -> 定时任务发送消息 -> 消费者确认 | 尽最大努力发送消息 -> 重试机制/死信队列 |
容错机制 | 通过回查机制保证最终一致性 | 通过定时任务和重试机制保证消息可靠性 | 重试机制和死信队列,无法完全保证送达 |
一致性 | 强一致性,消息与事务绑定 | 最终一致性,依赖重试机制和确认机制 | 无法保证一致性,只能最大努力保证送达 |
性能 | 较低,涉及事务回查等操作 | 较高,通过定时任务和重试机制管理 | 较高,适合对性能要求高但不要求严格一致性的场景 |
相关文章:

【分布式】万字图文解析——深入七大分布式事务解决方案
分布式事务 分布式事务是指跨多个独立服务或系统的事务管理,以确保这些服务中的数据变更要么全部成功,要么全部回滚,从而保证数据的一致性。在微服务架构和分布式系统中,由于业务逻辑往往会跨多个服务,传统的单体事务…...

apache2配置多站点
环境 ubuntu 14.04 apache2 Server version: Apache/2.4.7 (Ubuntu) Server built: Apr 3 2019 18:04:25 步骤 修改/etc/apache2/sites-enabled/000-default.conf 增加VirtualHost段,指定不同的ServerName、DocumentRoot等参数 <VirtualHost *:80>…...

基于PyQt Python的深度学习图像处理界面开发(一)
Python标准库更多的适合处理后台任务,唯一的图形库tkinter使用起来很不方便,所以后来出现了针对Python图形界面开发的扩展库,例如PyQt。 在介绍PyQt之前,必须先简单介绍一下Qt。Qt是一个C可视化开发平台,是一个跨平台的…...

【Linux网络】Linux网络编程套接字,UDP与TCP
📝个人主页🌹:Eternity._ ⏩收录专栏⏪:Linux “ 登神长阶 ” 🌹🌹期待您的关注 🌹🌹 ❀Linux网络编程套接字 📒1. 端口号📜2. 初识TCP协议与UDP协议…...

Vue3 -- 强制统一包管理器工具【企业级项目配置保姆级教程6】
引言: 团队开发项目的时候,需要统一包管理器工具,因为不同包管理器工具下载同一个依赖,可能版本不一样,导致项目出现bug问题,因此包管理器工具需要统一管理!!所以就需要我们强制统一包管理器工具。 创建scripts目录和preinstall.js文件: 在根目录创建scritps/preinstal…...

Winform实现自制浏览器JavaScript注入
让我们一起走向未来 🎓作者简介:全栈领域优质创作者 🌐个人主页:百锦再新空间代码工作室 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[1504566…...

【工具插件类教学】在 Unity 中使用 iTextSharp 实现 PDF 文件生成与导出
目录 一、准备工作 1. 安装 iTextSharp 2. 准备资源文件 二、创建 ExportPDFTool 脚本 1、初始化 PDF 文件,设置字体 2、添加标题、内容、表格和图片 三、使用工具类生成 PDF 四、源码地址 在 Unity 项目中,我们有时会需要生成带有文本、表格和图片的 PDF 文件,以便…...

javascript用来干嘛的?赋予网站灵魂的语言
javascript用来干嘛的?赋予网站灵魂的语言 在互联网世界中,你所浏览的每一个网页,背后都有一群默默工作的代码在支撑着。而其中,JavaScript就像是一位技艺精湛的魔术师,它赋予了网页生命力,让原本静态的页…...

Flutter Getx状态管理
在 Flutter 开发中,状态管理是一个非常重要的话题。随着应用变得更加复杂,状态管理的方式也变得越来越多。Flutter 提供了多种状态管理的解决方案,如 Provider、Riverpod、BLoC 等,而在这些选项中,GetX 作为一个轻量级…...

《成法》读书笔记
稻盛和夫的《成法》是一部关于个人和企业成功哲学的作品,结合了他在经营京瓷和KDDI,以及重建日航(JAL)过程中的经验和智慧。 以下是这本书的读书笔记,涵盖其核心思想和重要概念: 1. 以“心”为本 内容概…...

TensorFlow 2.0 环境配置
官方文档:CUDA Installation Guide for Windows 官方文档有坑,windows的安装指南直接复制了linux的指南内容:忽略这些离谱的信息即可。 可以从官方文档知悉,cuda依赖特定版本的C编译器。但是我懒得为了一个编译器就下载整个visua…...

Ekman理论回归
Scientific reportsEkman revisited: Surface currents to the left of the winds in the Northern HemisphereVagn Walfrid Ekman1905年的理论描述了地球旋转受到风的作用,摩擦边界层中的流场,北半球总是在海表风的右侧,南半球总是在海表风的…...

算法演练----24点游戏
给定4个整数,数字范围在1~13之间任意使用-*/(),构造出一个表达式,使得最终结果为24, 方法一 算法分析:加括号和取出重复表达式 # 导入精确除法模块,使得在Python2中除法运算的行为更…...

【学习心得】Python好库推荐——tiktoken
一、tiktoken是什么? tiktoken是一个快速BPE分词器,是由 OpenAI 开发的一个用于文本处理的 Python 库,主要用于将文本编码为数字序列(称为 "tokens"),或将数字序列解码为文本。这一过程被称为 &q…...

MacBook不额外安装软件,怎样投屏到安卓手机上?
提起iPhone或MacBook的投屏,人们总会想到airplay功能。但离开了苹果生态,其他品牌的手机电脑就未必配备airplay功能了。 如果想要将MacBook的电脑屏幕共享到安卓手机或平板上,到底要怎样做?需要安装什么软件吗? 不需要…...

flink sql + kafka + mysql 如何构建实时数仓
构建一个基于 Flink SQL、Kafka 和 MySQL 的实时数据仓库(Data Warehouse)架构,可以通过流处理的方式实现高效、实时的数据集成与分析。以下是如何利用这三者构建实时数仓的步骤与实现: 架构概述 Kafka:作为流数据平台,负责接收和传输来自不同源系统(如应用日志、传感器…...

Go语言开发基于SQLite数据库实现用户表查询详情接口(三)
背景 上一章 Go语言开发基于SQLite数据库实现用户表新增接口(二) 这一章我们实现用户表的查询详情接口 代码实现 mapper层 type UserMapper interface {GetById(id uint64) (*model.User, error)}type userMapper struct { }func (m *userMapper) GetById(id uint64) (*mod…...

(11)(2.1.7) FETtec OneWire ESCs(二)
文章目录 前言 3 组态 4 可选功能 5 SITL模拟 6 故障排除 前言 !Note 此功能在固件版本4.1.1及更高版本上可用。 3 组态 FTW掩码 SERVO_FTW_MASK 参数选择将哪些伺服输出(如果有的话)路由到 FETtec ESC。更改此参数后需要重新启动。…...

Springboot maven常见依赖、配置文件笔记
pom.xml文件 一、<parent> 在Maven项目中,pom.xml 文件中的 <parent> 元素用于定义父项目的坐标。使用 <parent> 可以实现继承机制,子项目可以从父项目继承配置信息,比如依赖管理、插件配置等。这样可以避免在多个子项目…...

Ceph后端两种存储引擎介绍
Ceph是一个可靠的、自治的、可扩展的分布式存储系统,它支持文件系统存储、块存储、对象存储三种不同类型的存储,以满足多样存储的需求。在Ceph的存储架构中,FileStore和BlueStore是两种重要的后端存储引擎,下面将分别进行详细介绍…...

C++入门基础知识140—【关于C++ 类构造函数 析构函数】
成长路上不孤单😊😊😊😊😊😊 【14后😊///C爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于C 类构造函数 & 析构函数的相关内容…...

基于标签相关性的多标签学习
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…...

macOS系统下使用SQLark连接达梦数据库
目录 下载 SQLark 客户端 安装 SQLark 客户端 SQLark用户界面 使用SQLark连接达梦数据库 1. 选择达梦数据库 2. 输入连接信息 3. 测试连接 4. 创建连接 5. 验证连接成功 作为一名数据库开发者,在macOS系统上找到一款支持达梦数据库的数据库开发和管理工具&…...

爬虫如何解决短效代理被封的问题?
在数据采集的征途上,短效代理如同一把双刃剑,它既能为我们带来速度和效率,也可能因为频繁更换IP地址而遭遇被封禁的风险。那么,作为数据采集er的我们,该如何巧妙应对,确保爬虫的稳定运行呢?今天…...

Jmeter基础篇(22)服务器性能监测工具Nmon的使用
一、前言 我们在日常做压测的过程中,不仅仅需要监控TPS,响应时间,报错率等这些系统基础性能数据,还需要对服务器的性能(如CPU、磁盘、内存、网络IO等)做监控,以求对系统运行过程中的硬件性能有…...

Spring Boot 集成 RabbitMQ:消息生产与消费详解
在现代微服务架构中,消息队列扮演着至关重要的角色,RabbitMQ 是其中一种广泛使用的消息中间件。本文将详细介绍如何在 Spring Boot 项目中集成 RabbitMQ,实现消息的生产和消费,并提供相应的代码示例。 一、环境准备与依赖配置 首…...

JSON-RPC-CXX深度解析:C++中的远程调用利器
一、引言 1. JSON-RPC 简介及其在 C 开发中的重要性 JSON-RPC(JavaScript Object Notation - Remote Procedure Call)是一种基于 JSON 格式的远程过程调用协议。在 C 开发中,它扮演着至关重要的角色。随着软件系统的日益复杂和分布式架构的…...

【后端速成Vue】模拟实现翻译功能
前言: 本期将会介绍 Vue 中的 watch 侦听器,它语法是怎么样的呢?具有怎样的功能呢?最后用模拟实现百度翻译来更进一步练习 watch 侦听器 篮球哥找工作专属IT岗位内部推荐: 专属内推链接:内推通道 1、认识翻…...

人脸识别技术:从算法到深度学习的全面解析
一、人脸识别技术综述 人脸识别技术作为一种重要的生物识别技术,在当今社会中具有举足轻重的地位。它广泛应用于各个领域,如金融领域的实名认证、安保领域的门禁系统、通行领域的火车站和地铁站检票、泛娱乐领域的美颜相机和短视频特效处理、公安和司法…...

WPF学习之路,控件的只读、是否可以、是否可见属性控制
C#的控件学习之控件属性操作 控件的只读、是否可以、是否可见,是三个重要的参数,在很多表单、列表中都有用到,正常表单控制可以在父层主键控制参数是否可以编辑和可见,但是遇到个别字段需要单独控制时,可以在初始化wi…...