秋招Day19 - 分布式 - 分布式事务

发布于:2025-07-27 ⋅ 阅读:(12) ⋅ 点赞:(0)

什么是分布式事务?

在分布式环境下,会涉及到多个服务以及数据库,比如支付库、商品库、订单库。不同的服务节点针对各自不同的数据库做操作想要保证一起成功或者一起回滚,就叫分布式事务。

分布式事务有哪些常见的解决方案?

两阶段提交(2PC):通过准备和提交阶段保证一致性,但有性能问题,也有数据不一致的风险

三阶段提交(3PC):在2PC的基础上添加了超时机制,降低了阻塞,但仍存在数据不一致的风险

TCC:Try、Confirm、Cancel

本地消息表:本地数据库执行完业务后,向本地消息表中插入一条消息,并通过定时任务处理消息的发送,发送或收到回应的时都会更新消息状态,也有重试机制

基于MQ的分布式事务:保证“本地事务”与“消息发送”的原子性,保证消息的可靠性。一个分布式事务由一系列本地事务组成,每个本地事务都会发布一个事件,触发下一个本地事务的执行。如果任何一个本地事务失败,就会触发一系列补偿事务来撤销之前已完成的操作。

说说2PC两阶段提交?

XA协议负责参与者(各个数据库)和协调者(全局事务管理器)之间通信。

第一阶段是准备,第二阶段是提交。

2PC主要包含以下角色:

  • AP/TM:某个应用程序全局事务的发起者和驱动者,管理事务边界
  • RM:资源管理器,也就是每个参数分布式事务的数据库实例,是分布式事务的参与者
  • TC:事务控制器,用来协调全局事务的提交和回滚,是分布式事务的协调者

参与者将准备阶段的成败告诉协调者然后阻塞等待指令,但凡有一个参与者的操作失败,协调者会向所有的参与者发出回滚请求;如果全部的参与者都操作成功,协调者会向所有参与者发出commit指令

缺点:

  • 单点问题:事务管理器在整个流程中扮演的角色很关键,如果其宕机,比如在第一阶段已经完成,在第二阶段正准备提交的时候事务管理器宕机,资源管理器就会一直阻塞,导致数据库无法使用。
  • 同步阻塞:在准备就绪之后,资源管理器中的资源一直处于阻塞,直到提交完成,释放资源。
  • 数据不一致:两阶段提交协议虽然为分布式数据强一致性所设计,但仍然存在数据不一致性的可能,比如在第二阶段中,假设协调者发出了事务 commit 的通知,但是因为网络问题该通知仅被一部分参与者所收到并执行了 commit 操作,其余的参与者则因为没有收到通知一直处于阻塞状态,这时候就产生了数据的不一致性。

3PC三阶段提交了解吗?

CanCommit(参与者检查资源)、PrepareCommit(参与者锁定资源,但不提交,超时也会提交)、DoCommit/AbortCommit(协调者长时间没有收到ACK,会发送Abort)

三阶段提交解决的只是两阶段提交中单点故障同步阻塞的问题,也会有数据不一致的问题,因为在3PC的第二阶段参与者等待超时会自动提交,而协调者在第三阶段如果检测到超时会Abort

TCC了解吗?

是两阶段提交的变种,只不过2PC锁的是数据库资源,TCC通过改变业务中的资源的当前状态,锁的是业务逻辑中的资源:

Try:预留或锁定所需的业务资源,比如库存是否充足、帐户余额是否足够,但不操作或锁定数据库

Confirm:协调者发现所有的参与者Try过程都成功了,则向所有参与者发送Confirm请求,让所有参与者的提交事务

Cancel:协调者发现有参与者的Try过程失败,则向所有参与者发送Cancel请求

本地消息表了解吗?

本地消息表的核心思想是将分布式事务拆分成本地事务进行处理。

将业务处理和后续调用其他服务的指令的消息(携带状态)的持久化放到一个本地事务中,要么业务成功且消息入库,要么都失败回滚。

一个独立的定时任务或服务会轮询本地消息表,将“待发送”的消息发送到 MQ。然后将消息状态修改为已发送

另一个服务执行成功,修改调用者的本地消息表中的对应消息状态为已成功或直接删除

失败则重试,保证最终一致性

MQ消息事务了解吗

本地消息表是将消息入库和业务逻辑合并为一个原子性事务,该事务提交后再异步轮询发送消息,MQ消息事务是本地事务提交后直接将消息提交到MQ,并有回查机制

  • 生产者发送半消息: 生产者向 MQ 发送一个“半消息”(或称预提交消息),此时消息对消费者不可见。

  • 执行本地事务: 生产者执行自己的本地数据库事务。

  • 生产者通知 MQ 提交/回滚:

    • 如果本地事务成功,生产者通知 MQ 提交半消息,消息变为可见。

    • 如果本地事务失败,生产者通知 MQ 回滚半消息,消息被丢弃。

  • MQ 回查机制: 如果生产者在本地事务提交后但在通知 MQ 之前崩溃,MQ 会主动回查生产者,询问本地事务的最终状态,然后决定提交还是回滚半消息。

最大努力通知了解吗?

发送方完成并提交自己的本地事务后,尽最大的努力通知接受方结果,发送不成功就一致重试,直到最大次数。然后接受方再执行后续的业务逻辑。尽最大可能实现最终一致性。

你们业务中用的什么?能说一下Seata吗?

我们用的是基于2PC的分布式事务解决方案Seata,因为自己实现分布式事务太麻烦了。

主要有三个角色:

  • RM;负责具体的本地事务执行,负责和TC注册本地事务
  • TM:事务边界管理者,用来开启、回滚、提交事务
  • TC:全局事务协调者,用来向各个参与者发送提交或回滚指令

具体过程是:

TM向TC申请一个开启全局事务,TC向TM返回一个代表全局事务的XID,RM负责执行当前的本地事务并向TC注册事务分支。当前本地事务执行完后,TM会调用下一个服务并传递XID,下一个服务的RM再执行相应的本地事务并向TC注册事务分支,以此类推。如果某个服务的业务执行过程中出现异常,当前服务的TM会向TC发起回滚请求,TC再协调全局的回滚。


网站公告

今日签到

点亮在社区的每一天
去签到