{"name":"分布式事务","id":"软件工程-架构-系统设计-分布式-分布式事务","content":"# 分布式事务\n\n## 第一性原理：事务能力的构成\n\n### 两块机制\n\n**事务不是数据库特性，而是一种状态一致性约束机制。**\n\n事务能力由两块机制供给：\n\n| 机制族 | 根本问题 | ACID 投影 |\n|--------|---------|----------|\n| **Recovery** | 故障下，状态的定义如何保持明确 | A、D |\n| **Concurrency Control** | 并发交错下，可见性如何受控 | I |\n| （应用契约，非机制） | 业务不变式是否成立 | C |\n\n**A 与 D 同源**：共用日志 + 恢复算法。undo 支撑 A，redo 支撑 D，差别只在故障时点与观察视角。\n\n两块机制共同依赖一个东西：**状态变更的全序**。恢复需要它判定“哪些已生效”，并发控制需要它判定“谁看得见谁”。\n\n### 分布式的唯一损失：全序退化为偏序\n\n> CAP/FLP理论（详见[分布式理论](分布式理论.md)、[分布式共识算法](分布式共识算法.md)），\n> 本篇文档聚焦：**当”事务”这一抽象遇到分布式环境时，发生了什么质变。**\n\n单机不争取全序，它天然拥有：单一 WAL 的 LSN 序给出变更全序，单一发号器给出可见性基准。**同一个全序同时供养 A 和 I**，二者搭同一班车，因此单机语境几乎无需区分。\n\n分布式只有偏序。这一个损失，把合一的机制劈成三个代价迥异的问题：\n\n| 投影 | 是否仍可获得 | 代价 |\n|------|------------|------|\n| **A** | 能 | 退化为共识问题 |\n| **I** | 需把全序买回来 | 需全局排序设施 |\n| **D** | 未退化，但边界收缩 | 幂等 + 至少一次投递（Outbox） |\n\n> **原子提交 ≡ 共识**。这一等价使 FLP 与 CAP 的约束直接作用于事务提交——2PC 的阻塞由此成为推论。\n\nA 未被打破，只是被重新定价：多数业务放弃它出于成本，不出于不可能。\n\n**D 的变化是边界收缩。** 耐久度没降,变的是覆盖范围:单机持久化天然对所有参与者生效(共享存储),分布式下只覆盖本地——数据落盘了,但别的服务不知道。\n\n于是持久化对象必须从状态扩到意图:不仅存”订单已付款”,还要存”需通知库存服务”这个待办。Outbox 就是把这个待办也纳入事务,让持久性边界重新覆盖跨服务通知。\n\n代价:幂等由可选变强制(重发必然发生),且多出单机没有的中间态——已本地提交、尚未对外可见。\n\n**推导出的本质矛盾**：\n\n> **”原子性”要求操作不可分割；  \n> “分布式”本质上就是将操作分布到多个独立决策点。**\n>\n> 二者的交集需要一个全局全序，而分布式恰好不提供它。\n\n### 模式层：对全序的四种取舍\n\n| 取舍 | 手法 | 代价 | 代表 |\n|------|------|------|------|\n| **模拟全序** | 协议内构造单一决策点 | 可用性（阻塞、协调者单点） | 2PC / XA |\n| **购买全序** | 引入全局排序设施 | 部署成本与延迟 | TSO、TrueTime 类 |\n| **放弃 + 语义补偿** | 向前追加撤销语义 | A 降为近似，I 失守 | Saga / TCC |\n| **放弃 + 收敛** | 异步驱动状态机 | 仅保证最终一致 | 事务消息 |\n\n**真正不可逆的是 I。** 补偿能让最终结果收敛到 all-or-nothing 的语义等价物，却无法让别人没看见过中间态。A 有成熟套路（补偿 + 幂等 + 重试 + DLQ），I 无通用解——只能按场景在应用层逐一打补丁（见下文工程对策）。\n\n**隔离性随“放弃全序的程度”单调递减**——中间态如何暴露，决定 I 的存亡：\n\n| 方案 | 中间态形态 | I |\n|------|-----------|---|\n| 2PC / XA | 阻塞到决议，不外显 | 强 |\n| TCC | 预留态：设计出的合法业务态 | 业务保证 |\n| Saga | 真实中间态直接外显 | 弱 |\n| 消息事务 | 不加控制 | 无 |\n\nTCC 以更高业务侵入（每个资源都要设计预留语义）换回部分 I；Saga 暴露真实中间态；消息事务彻底放弃。\n\n#### 隔离性与补偿的工程对策\n\nI 无通用解——上文四种取舍中，凡“放弃全序”的方案都要在应用层逐一打补丁。常见手法：\n\n| 手法 | 机制 | 代价 |\n|------|------|------|\n| 语义锁 | 中间态标记 PENDING，阻止他人误读 | 引入应用层锁，退化出部分阻塞 |\n| 交换律更新 | Append-Only / 增量操作，消除写冲突 | 仅适用可交换语义 |\n| 悲观视图 | 未决数据对外不可见 | 牺牲时效与可用性 |\n| 重读校验 | 提交前重读比对（OCC 式） | 冲突高时反复重试 |\n\n这些只能压低脏读概率、缩小暴露窗口，无法根除中间态可见——I 的失守是放弃全序的必然代价，工程上只能控制而非消除。\n\n### 横向同构：全序稀缺是跨尺度母题\n\n| 尺度 | 全序设施 | 放弃后的形态 |\n|------|---------|------------|\n| 单核 | 程序顺序 | — |\n| 多核 CPU | 总线序 / 缓存一致性协议 | 弱内存模型 + 内存屏障按需重建 |\n| 单机多库 | 无 | 2PC 模拟 |\n| 跨服务 | 无 | Saga 补偿 / 事件收敛 |\n| 事件溯源 | 分区内序 | 因果序 + 幂等消费 |\n\n> **不变规律**：每次系统尺度扩大，全序都变得更贵；应对手法始终只有三种——模拟它、购买它、或放弃它并在语义层重建。\n\n这一取舍框架决定了后续所有方案的设计哲学。\n\n## 分布式事务抽象模型\n\n### 方案的本质分类:决策粒度\n\n所有分布式事务方案,按**决策的原子单位**可归为两类:\n\n#### 单决策协调:就一个结果达成一致\n\n**决策对象**:COMMIT 还是 ABORT,一个比特。\n\n**抽象模型**:\n```\n所有参与者 → 投票 → 协调者汇总 → 广播统一决策\n```\n\n**核心约束**:\n- 必须等待:决策前需收齐所有投票\n- 必须一致:所有人看到同一个决策\n- 代价来源:等待 = 阻塞,一致 = 共识成本\n\n**典型**:2PC、XA。适合金融核心账务、低并发强一致场景\n\n> 本质:这是**共识问题**在事务上的应用。一旦映射到共识,FLP/CAP 的约束自动生效——阻塞或放弃一致性,二选一。\n\n#### 多步骤编排:协调一串操作的执行与撤销\n\n**决策对象**:每一步是否继续,以及失败后如何补偿,N 个决策。\n\n**抽象模型**:\n```\n步骤1 → 步骤2 → ... → 步骤N\n  ↓       ↓             ↓\n补偿1   补偿2         补偿N\n```\n\n**核心约束**:\n- 状态外显:每步结果对外可见,需业务建模\n- 补偿必备:失败时只能向前追加撤销操作\n- 代价来源:编排复杂度 + 隔离性失守\n\n**典型**:Saga、TCC、事务消息\n\n> 本质:这是**工作流编排**问题。与 Kubernetes Job、AWS Step Functions、BPMN 同构——都在管理\"多步骤如何在失败时安全回退\"。\n\n**TCC**:每个参与方提供三阶段接口:\n- Try:预留资源(如冻结余额)\n- Confirm:确认提交\n- Cancel:释放资源\n\n关键问题:\n- 悬挂:Cancel 先于 Try 到达,需状态标记防重\n- 幂等:三个阶段均需幂等实现\n\n适合短流程、资源可预留、需较强隔离的账务类操作。\n\n**Saga**:正向事务序列 + 逆序补偿链。中间态外显,需业务建模。适合长事务、核心交易但需高可用场景。\n\n**消息驱动最终一致性**:\n\n| 模式 | 机制 | 适用 |\n|------|------|------|\n| **事务消息** | MQ 提供事务语义,本地事务与发消息绑定 | 同一组织内 |\n| **本地消息表** | 消息作为数据写入业务库,轮询/CDC 投递 | 无事务 MQ 时 |\n| **最大努力通知** | 重试 N 次后放弃,接收方主动查询兜底 | 跨组织、跨网络 |\n\n统一抽象:本地事务保证状态落盘 → 消息保证状态传播 → 重试保证收敛。\n\n#### 分类的稳定性\n\n| 维度 | 单决策协调 | 多步骤编排 |\n|------|----------|-----------|\n| 问题映射 | 共识(Consensus) | 编排(Orchestration) |\n| 时间尺度 | 瞬时(ms-s) | 长期(s-min-h) |\n| 失败处理 | 回滚(UNDO) | 补偿(Compensation) |\n| 理论工具 | 分布式系统理论 | 工作流理论 |\n\n## 治理视角：一致性责任的组织化\n\n### 为什么必然出现治理层\n\n分布式事务把一致性保证从**数据库自动兜底**下沉为**应用显式维护**。三个质变随之发生：\n\n| 维度 | 单机 | 分布式 |\n|------|------|--------|\n| 一致性 | 系统属性，自动保证 | 运营对象，需持续维护 |\n| 不一致 | 异常，不应出现 | 常态，存在可接受窗口（soft state） |\n| 兜底责任 | 存储层 / DBA | 业务团队 |\n\n系统不再自动兜底，组织必须补上。治理层不是附加运维，而是**用组织流程重新实现数据库放弃的那部分一致性**。\n\n### 治理的本质：检测—收敛闭环\n\n补偿只覆盖**已知失败路径**，无法处理未知漂移（消息丢失、补偿自身失败、代码 bug、状态损坏）。因此需要一个独立于事务链路的闭环——**检测不一致 → 收敛不一致**，分层防御，自动优先、人工兜底：\n\n| 层 | 职责 | 核心设施 | 关键指标 |\n|----|------|---------|---------|\n| 可观测 | 发现卡单与漂移 | 事务日志 / 状态机 + 全局 correlation ID | 卡单率、补偿失败率、不一致窗口时长 |\n| 自动收敛 | 消化已知失败 | 重试 + 死信队列 + 定时补偿 | 重试成功率、DLQ 堆积量 |\n| 对账 | 兜住未知漂移 | 独立于主链路的业务级校验 | 对账差异数、修复时延 |\n| 人工兜底 | 处理无法自愈 | 告警 + runbook + SLA | 人工介入次数、MTTR |\n\n### 对账：比补偿更底层的安全网\n\n| | 补偿 | 对账 |\n|---|------|------|\n| 触发 | 事务链路内，失败即触发 | 独立周期运行 |\n| 覆盖 | 已知失败路径 | 任意来源的最终不一致 |\n| 依赖 | 依赖链路本身正常 | 不依赖链路，直接比对终态 |\n\n补偿失败、消息丢失、程序缺陷造成的漂移，只有对账能发现并修复。**补偿处理“已知的失败”，对账兜住“未知的漂移”**——后者是前者的最后一道防线。\n\n### 组织维度：Conway 定律的投影\n\n补偿链与对账逻辑天然**跨服务**，而服务边界即团队边界。由此派生的都不是纯技术问题：\n\n- 跨服务的补偿 / 对账由谁 own（横切多个团队）\n- on-call 与变更治理必须匹配分布式拓扑，而非沿用单库时代\n- **一致性预算**（哪些不一致、多久窗口可接受）是产品决策，非工程决策\n\n这是“系统越分布，事务越业务化”的组织投影：一致性的 **C** 从数据库内的约束，变成跨团队协作的契约。\n\n## 稳定内核\n\n1. 事务能力 = 恢复 + 并发控制，二者共同依赖**状态变更的全序**\n2. 分布式的唯一损失：全序退化为偏序，把合一的机制劈成三个代价迥异的问题\n   - A → 退化为共识（原子提交 ≡ 共识）\n   - I → 无通用解，只能在应用层逐一打补丁\n   - D → 未退化，但边界收缩（Outbox）\n3. **真正不可逆的是 I**：补偿能补回 A，补不回“别人已看见中间态”\n4. 方案按**决策粒度**分两类：单决策协调（共识）/ 多步骤编排（编排）\n5. 一致性责任下沉到组织：补偿处理已知失败，对账兜住未知漂移\n\n## 关联内容（自动生成）\n\n- [/软件工程/架构/系统设计/分布式/分布式共识算法.md](/软件工程/架构/系统设计/分布式/分布式共识算法.md) 原子提交等价于共识，共识算法是单决策协调类方案的理论内核\n- [/软件工程/架构/系统设计/分布式/分布式理论.md](/软件工程/架构/系统设计/分布式/分布式理论.md) CAP/FLP 界定了分布式事务的能力边界，是四种取舍的理论前提\n- [/中间件/数据库/数据库系统/事务管理/事务.md](/中间件/数据库/数据库系统/事务管理/事务.md) 单机 ACID 与全序是分布式事务的对照基线，本文的三投影由此推导\n- [/软件工程/架构/系统设计/分布式/分布式一致性与协调机制.md](/软件工程/架构/系统设计/分布式/分布式一致性与协调机制.md) 分布式事务依赖一致性协调机制解决状态同步与决策一致\n- [/中间件/数据库/分布式数据库.md](/中间件/数据库/分布式数据库.md) 分布式数据库是分布式事务的主要应用场景，内建 2PC/复制等协议\n- [/编程语言/JAVA/JVM/JAVA内存模型.md](/编程语言/JAVA/JVM/JAVA内存模型.md) 多核弱内存模型与内存屏障是“全序稀缺”在处理器尺度的同构投影\n- [/中间件/消息队列/消息队列.md](/中间件/消息队列/消息队列.md) 可重放日志与投递语义是消息驱动最终一致性方案的机制基座\n- [/软件工程/微服务/服务治理/服务容错.md](/软件工程/微服务/服务治理/服务容错.md) 治理节的重试/DLQ/人工兜底与容错“常态失败下维持稳态”同源\n- [/计算机网络/rpc.md](/计算机网络/rpc.md) RPC 是跨服务编排类方案的底层调用机制，其失败语义直接影响事务设计\n","metadata":"tags: ['分布式系统', '事务管理', '数据库', 'cap定理']\nlinks: [\n    'https://icyfenix.cn/architect-perspective/general-architecture/transaction/distributed.html#saga-%E4%8A%9A%E4%BA%8B%E5%8A%A1'\n]","hasMoreCommit":false,"totalCommits":2,"commitList":[{"date":"2026-08-18T10:47:55+08:00","author":"My","message":"Merge pull request #583 from 0xcaffebabe/renovate/npm-mermaid-vulnerability","hash":"321262974de1264492f8cc98582a1a488e050fae"},{"date":"2026-08-14T22:01:57Z","author":"renovate[bot]","message":"fix(deps): update dependency js-yaml to v4.3.1 [security]","hash":"d26a4e412e44626a9dce4c7cee840737ffe1b089"}],"createTime":"2026-08-14T22:01:57Z"}