logo
Database Design

Distributed Transactions

分布式事务的挑战

Distributed transaction 是跨两个或多个 databases 的一组数据操作。它通常在网络连接的多个 nodes 上协调执行,也可能发生在同一 server 上的多个 databases。

为什么需要 distributed transactions?

单库里的 ACID transaction 只影响一个 database;但 distributed transaction 需要在多个 databases 上改数据,所以协调 commit / rollback 更复杂。

换句话说:要么所有 nodes 都 commit,要么全部 abort 并整体 rollback。这就是 distributed transactions 存在的原因。

下面是一些常见方案。

Two-Phase Commit (2PC)

two-phase-commit

Two-Phase Commit 是一种分布式协议,用来协调所有参与节点决定 commit 还是 abort(rollback)。

它能在很多临时故障场景下继续工作,因此被广泛使用。但它无法覆盖所有故障组合,极少数情况下可能需要人工干预。

2PC 需要一个 coordinator node,负责在多个节点间协调 transaction。它分两阶段建立共识:

Phases

Prepare phase

Coordinator 向各 participant 收集是否“准备好”的共识。如果任一节点未准备好,transaction 会被 abort。

Commit phase

如果所有 participant 都返回 prepared,coordinator 就通知所有节点 commit。若此时发生失败,transaction 需要 rollback。

Problems

  • 某个节点 crash 了怎么办?
  • coordinator 自己 crash 了怎么办?
  • 这是一个 blocking protocol。

Three-Phase Commit (3PC)

three-phase-commit

3PC 是 2PC 的扩展,把 commit 阶段拆成两步,用来缓解 2PC 的 blocking 问题。

Phases

Prepare phase

同 2PC。

Pre-commit phase

Coordinator 发出 pre-commit,所有 participant 必须确认。如果某个节点超时未收到,则 transaction abort。

Commit phase

与 2PC 的 commit 类似。

为什么 Pre-commit 有用?

  • 如果 participant 处于 pre-commit,说明所有人都完成了 prepare。
  • 每个 phase 都可以 timeout,避免无限等待。

Sagas

sagas

Saga 是一系列 local transactions。每个 local transaction 更新 database 并发布 message/event 触发下一个 local transaction。如果某个 local transaction 因业务规则失败,就执行一系列 compensating transactions 来撤销之前的改动。

Coordination

常见两种实现:

  • Choreography:每个 local transaction 发布 domain events,触发其他服务的 local transactions。
  • Orchestration:由 orchestrator 统一指挥各参与者执行本地事务。

Problems

  • Saga pattern 很难 debug。
  • 容易产生参与者之间的循环依赖。
  • 缺乏 participant 的数据隔离会带来 durability 挑战。
  • 测试困难,因为需要所有服务同时运行才能模拟 transaction。

相关练习题

Distributed Transactions

暂无相关练习题