简介:本文从一致性理论出发,系统梳理分布式事务的核心矛盾与主流解决方案,包括两阶段提交、补偿事务、可靠消息最终一致、本地消息表与事务消息等思路,并给出选型维度与落地要点。读者可据此理解CAP与BASE的工程含义,掌握不同方案的适用边界、失败处理与幂等设计方法。
在单库单机场景下,事务的 ACID 特性由数据库引擎直接保障:原子性确保操作全成或全败,一致性维护约束不被破坏,隔离性控制并发可见性,持久性保证提交结果不丢失。一旦业务按业务域拆分为多个数据源,一次业务操作需要跨多个库、多个服务完成写入,原本在一个事务边界内的问题就被拆散到网络两侧。
跨库事务面临的核心困难在于:网络请求可能超时而非明确失败,参与节点可能永久性宕机,重试可能造成重复写入,部分成功后的回滚也可能自身失败。此时若仍期望每个时刻都保持强一致,往往要以牺牲可用性或吞吐为代价。因此讨论分布式事务,首先要接受一个前提:一致性不是免费的,它是一个需要在可用性、延迟、复杂度之间做显式取舍的工程目标。
CAP 理论指出,分布式系统在一致性(Consistency)、可用性(Availability)、分区容忍性(Partition Tolerance)三个要素中最多同时满足两个。需要强调的是,分区容忍性在真实网络中不是可选项——网络分区迟早发生,因此实际决策通常是在分区发生时选择 C 还是 A。
工程上常见两类默认倾向:一类系统优先保证可用性与分区容忍,弱化强一致,接受最终一致;另一类系统优先保证一致性与分区容忍,在分区时可能拒绝部分请求。前者适合高并发读写、对短暂不一致不敏感的场景,后者适合元数据、配置、账务约束等对正确性要求高的场景。
BASE 理论是对大规模分布式系统实践的总结,包含三个要点:
BASE 的价值在于把“一致性”从瞬时约束放宽为过程约束,从而为水平扩展、异步化、失败重试留出空间。它并不意味着放弃正确性,而是要求系统显式设计中间状态、补偿路径与收敛机制。
两阶段提交协议(2PC)是最经典的分布式事务协议,引入协调者角色,将提交拆为两个阶段:
示意性流程如下:
协调者 参与者A 参与者B|--- prepare ------->|--- 本地执行、加锁 -->||--- prepare ---------------------------->|--- 本地执行、加锁|<-- yes -------------|<-- yes -------------||--- commit --------->|--- 提交 ----------->||--- commit ---------------------------->|--- 提交
2PC 的优点语义清晰、强一致,但代价同样明显:
因此 2PC 更适合参与者数量有限、事务时长可控、对强一致要求高的场景,而不宜作为大规模微服务链路的默认方案。
TCC 将业务操作拆为 Try、Confirm、Cancel 三个阶段:Try 预留资源并做业务检查,Confirm 使用预留资源完成实际写入,Cancel 释放预留资源。它把锁的粒度从数据库行级上移到业务资源级,减少长事务对数据库的占用。
TCC 的关键难点在于:Cancel 必须幂等且能处理“空回滚”(Try 未执行却收到 Cancel)与“悬挂”(Cancel 先于 Try 到达)。工程上通常需要事务控制表记录每个分支的执行状态,并配合重试与对账。TCC 适合资源预留语义明确的业务,如库存扣减、额度冻结,但对业务侵入较大。
该思路把跨库写入转化为“本地写入 + 消息投递”的组合:业务在本地事务中完成业务数据写入,同时把待发送消息持久化到本地消息表,保证两者在同一本地事务中原子生效;随后由独立投递组件读取消息表并投递到消息队列,下游消费成功后进行确认。
本地事务 {写入业务数据写入本地消息表(状态=待投递)}投递组件轮询消息表 -> 发送到消息队列 -> 下游消费 -> 标记已投递
该方案的要点包括:消息表与业务表同库以保证原子性;投递组件至少一次投递,因此下游必须幂等;需要失败重试、死信处理与对账补偿。它适合链路较长、允许短暂延迟的最终一致场景。
事务消息可视为可靠消息思路的托管化形态:生产者先发送半消息,服务端暂不投递;生产者执行本地事务后提交二次确认,服务端据结果决定投递或丢弃;若二次确认缺失,服务端通过回查机制向生产者确认本地事务状态。它降低了自建消息表的运维成本,但同样要求下游消费幂等,并需要处理回查逻辑。
对于非核心链路,可采用最大努力通知:业务方在本地事务完成后,按一定策略重复通知下游,下游处理后应答;若多次通知仍失败,则进入人工或定时对账流程。该方案实现简单、侵入小,但一致性保障最弱,适合通知类、积分类等对时效与严格性要求不高的场景。
方案选择应从以下维度评估:
落地时必须统一处理三件事:幂等(同一请求重复执行结果不变,可用唯一业务键加去重表)、重试(退避策略与最大次数)、对账(定时比对两侧数据并修复差异)。缺少任何一项,最终一致都只是理论上的收敛。
分布式事务没有银弹。强一致路线以 2PC 为代表,语义清晰但扩展性受限;最终一致路线以补偿事务、可靠消息、事务消息、最大努力通知为代表,通过放宽瞬时一致性换取可用性与扩展性,但要求系统显式设计中间状态、幂等、重试与对账。正确的做法是先明确业务对一致性的真实要求,再选择匹配的方案,并把失败路径当作一等公民来设计。