2026-02-15 01:57:52 +08:00
|
|
|
|
# 分布式系统的挑战
|
|
|
|
|
|
|
2026-02-26 04:35:28 +08:00
|
|
|
|
::: tip 前言
|
|
|
|
|
|
**当一台机器不够用时,问题才真正开始。** 分布式系统是现代互联网的基石——从微信消息到淘宝下单,背后都是成百上千台机器协同工作。但"分布式"不是免费的午餐,它带来了一系列单机系统从未遇到的挑战。
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
**这篇文章会带你学什么?**
|
|
|
|
|
|
|
|
|
|
|
|
学完这章后,你将获得:
|
|
|
|
|
|
|
|
|
|
|
|
- **核心定理**:理解 CAP 定理及其对系统设计的影响
|
|
|
|
|
|
- **一致性模型**:区分强一致性、最终一致性、因果一致性
|
|
|
|
|
|
- **八大挑战**:掌握分布式系统面临的核心难题
|
|
|
|
|
|
- **共识算法**:了解 Paxos、Raft 等分布式共识的基本思想
|
|
|
|
|
|
- **实战模式**:熟悉 2PC、Saga、CRDT 等常用解决方案
|
|
|
|
|
|
|
|
|
|
|
|
| 章节 | 内容 | 核心概念 |
|
|
|
|
|
|
|-----|------|---------|
|
|
|
|
|
|
| **第 1 章** | 为什么需要分布式 | 扩展性、可用性、地理分布 |
|
|
|
|
|
|
| **第 2 章** | CAP 定理 | 一致性、可用性、分区容错 |
|
|
|
|
|
|
| **第 3 章** | 一致性模型 | 强一致、最终一致、因果一致 |
|
|
|
|
|
|
| **第 4 章** | 八大挑战 | 网络、时钟、分区、脑裂等 |
|
|
|
|
|
|
| **第 5 章** | 共识算法 | Paxos、Raft、ZAB |
|
|
|
|
|
|
| **第 6 章** | 分布式事务 | 2PC、Saga、TCC |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 0. 全景图:为什么需要分布式系统?
|
|
|
|
|
|
|
|
|
|
|
|
单机系统简单可靠,但有三个无法逾越的瓶颈:
|
|
|
|
|
|
|
|
|
|
|
|
| 瓶颈 | 说明 | 分布式的解法 |
|
|
|
|
|
|
|------|------|-------------|
|
|
|
|
|
|
| 性能上限 | 单机 CPU、内存、磁盘有物理极限 | 水平扩展:加更多机器分担负载 |
|
|
|
|
|
|
| 单点故障 | 一台机器挂了,整个服务就挂了 | 冗余副本:多台机器互为备份 |
|
|
|
|
|
|
| 地理延迟 | 用户在全球各地,单机只能在一个地方 | 多地部署:就近服务用户 |
|
|
|
|
|
|
|
|
|
|
|
|
::: tip 分布式的代价
|
|
|
|
|
|
分布式系统解决了上面的问题,但引入了新的复杂性:网络不可靠、时钟不同步、部分失败、数据一致性……这些就是本文要讨论的"挑战"。
|
|
|
|
|
|
|
|
|
|
|
|
**Peter Deutsch 的分布式计算八大谬误**告诉我们,以下假设在分布式环境中都是错的:
|
|
|
|
|
|
1. 网络是可靠的
|
|
|
|
|
|
2. 延迟是零
|
|
|
|
|
|
3. 带宽是无限的
|
|
|
|
|
|
4. 网络是安全的
|
|
|
|
|
|
5. 拓扑不会变化
|
|
|
|
|
|
6. 只有一个管理员
|
|
|
|
|
|
7. 传输成本是零
|
|
|
|
|
|
8. 网络是同构的
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 1. CAP 定理:分布式系统的"不可能三角"
|
|
|
|
|
|
|
|
|
|
|
|
2000 年,Eric Brewer 提出了 CAP 猜想(后被证明为定理):一个分布式系统最多只能同时满足以下三个属性中的两个。
|
|
|
|
|
|
|
|
|
|
|
|
| 属性 | 含义 | 通俗理解 |
|
|
|
|
|
|
|------|------|---------|
|
|
|
|
|
|
| **C**onsistency(一致性) | 所有节点在同一时刻看到相同的数据 | 你在任何 ATM 查余额,结果都一样 |
|
|
|
|
|
|
| **A**vailability(可用性) | 每个请求都能收到非错误的响应 | 系统永远能回应你,不会说"服务不可用" |
|
|
|
|
|
|
| **P**artition tolerance(分区容错) | 网络分区时系统仍能继续运行 | 即使部分网线断了,系统还能工作 |
|
|
|
|
|
|
|
|
|
|
|
|
<CAPTheoremDemo />
|
|
|
|
|
|
|
|
|
|
|
|
### 为什么只能选两个?
|
|
|
|
|
|
|
|
|
|
|
|
在分布式环境中,网络分区(P)是不可避免的——光纤会被挖断、交换机会故障、数据中心会断网。所以 P 是必选项,实际的选择是在 C 和 A 之间权衡:
|
|
|
|
|
|
|
|
|
|
|
|
- **选 CP**:分区时拒绝不确定的请求,保证数据正确 → 适合金融、库存
|
|
|
|
|
|
- **选 AP**:分区时继续服务,但数据可能暂时不一致 → 适合社交、内容
|
|
|
|
|
|
|
|
|
|
|
|
::: tip CAP 不是非黑即白
|
|
|
|
|
|
现实中的系统不是简单的"CP 或 AP"。很多系统在不同操作上做不同的选择——比如同一个数据库,读操作可以是 AP(允许读旧数据),写操作可以是 CP(要求多数确认)。
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 2. 一致性模型:数据同步的"严格程度"
|
|
|
|
|
|
|
|
|
|
|
|
一致性不是一个开关(有或没有),而是一个光谱。不同的一致性模型在"正确性"和"性能"之间做不同的权衡。
|
|
|
|
|
|
|
|
|
|
|
|
<ConsistencyModelsDemo />
|
|
|
|
|
|
|
|
|
|
|
|
### 一致性模型对比
|
|
|
|
|
|
|
|
|
|
|
|
| 模型 | 保证 | 延迟 | 适用场景 |
|
|
|
|
|
|
|------|------|------|---------|
|
|
|
|
|
|
| 强一致性 | 读到的一定是最新写入的值 | 高(需等待同步) | 银行转账、库存扣减 |
|
|
|
|
|
|
| 最终一致性 | 最终所有副本会一致,但中间可能读到旧值 | 低(写入立即返回) | 社交动态、DNS |
|
|
|
|
|
|
| 因果一致性 | 有因果关系的操作保证顺序 | 中等 | 评论回复、协作编辑 |
|
|
|
|
|
|
| 线性一致性 | 所有操作看起来像在单机上按顺序执行 | 最高 | 分布式锁、选主 |
|
|
|
|
|
|
| 会话一致性 | 同一会话内保证读到自己的写入 | 低-中 | 用户个人数据 |
|
|
|
|
|
|
|
|
|
|
|
|
::: tip "读己之写"一致性
|
|
|
|
|
|
最常见的实际需求是:用户修改了自己的数据后,自己能立即看到更新(但其他用户可以稍后看到)。这叫"Read Your Own Writes"一致性,是最终一致性的一个实用增强。
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 3. 八大挑战:分布式系统的"地雷阵"
|
|
|
|
|
|
|
|
|
|
|
|
分布式系统的复杂性不是来自某一个问题,而是多个问题交织在一起。以下是最核心的八大挑战。
|
|
|
|
|
|
|
|
|
|
|
|
<DistributedChallengesDemo />
|
|
|
|
|
|
|
|
|
|
|
|
### 挑战之间的关联
|
|
|
|
|
|
|
|
|
|
|
|
这八大挑战不是孤立的,它们相互关联:
|
|
|
|
|
|
|
|
|
|
|
|
- **网络不可靠** → 导致 **网络分区** → 触发 **CAP 权衡**
|
|
|
|
|
|
- **时钟不同步** → 导致 **事件排序困难** → 影响 **数据一致性**
|
|
|
|
|
|
- **部分失败** → 可能导致 **脑裂** → 需要 **共识算法** 来解决
|
|
|
|
|
|
- **数据一致性** → 需要 **分布式事务** → 但事务又受 **网络不可靠** 影响
|
|
|
|
|
|
|
|
|
|
|
|
::: tip 没有银弹
|
|
|
|
|
|
分布式系统没有"完美"的解决方案,只有"合适"的权衡。理解这些挑战的本质,才能在设计系统时做出正确的取舍。
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 4. 共识算法:如何让多台机器"达成一致"
|
|
|
|
|
|
|
|
|
|
|
|
共识算法是分布式系统的核心——它解决的问题是:多个节点如何就某个值达成一致?即使部分节点故障或网络延迟。
|
|
|
|
|
|
|
|
|
|
|
|
### 4.1 Paxos
|
|
|
|
|
|
|
|
|
|
|
|
Leslie Lamport 在 1990 年提出,是第一个被严格证明正确的共识算法。
|
|
|
|
|
|
|
|
|
|
|
|
| 角色 | 职责 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| Proposer | 提出提案(值) |
|
|
|
|
|
|
| Acceptor | 投票接受或拒绝提案 |
|
|
|
|
|
|
| Learner | 学习最终被选定的值 |
|
|
|
|
|
|
|
|
|
|
|
|
**两阶段流程**:
|
|
|
|
|
|
1. **Prepare 阶段**:Proposer 发送提案编号,Acceptor 承诺不再接受更小编号的提案
|
|
|
|
|
|
2. **Accept 阶段**:Proposer 发送具体值,多数 Acceptor 接受则提案通过
|
|
|
|
|
|
|
|
|
|
|
|
::: tip Paxos 的问题
|
|
|
|
|
|
Paxos 虽然正确,但出了名的难以理解和实现。Lamport 自己的论文用了一个希腊议会的比喻,结果让更多人困惑了。
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
### 4.2 Raft:为可理解性而生
|
|
|
|
|
|
|
|
|
|
|
|
2014 年 Diego Ongaro 提出 Raft,目标是做一个"容易理解的 Paxos"。它把共识问题分解为三个子问题:
|
|
|
|
|
|
|
|
|
|
|
|
| 子问题 | 说明 |
|
|
|
|
|
|
|--------|------|
|
|
|
|
|
|
| Leader 选举 | 集群中选出一个 Leader,所有写入都经过 Leader |
|
|
|
|
|
|
| 日志复制 | Leader 将操作日志复制到所有 Follower |
|
|
|
|
|
|
| 安全性 | 保证已提交的日志不会被覆盖 |
|
|
|
|
|
|
|
|
|
|
|
|
**Raft 的核心流程**:
|
|
|
|
|
|
1. 集群启动时,所有节点都是 Follower
|
|
|
|
|
|
2. 如果 Follower 超时没收到 Leader 心跳,就变成 Candidate 发起选举
|
|
|
|
|
|
3. 获得多数票的 Candidate 成为新 Leader
|
|
|
|
|
|
4. Leader 接收客户端请求,将日志复制到多数节点后提交
|
|
|
|
|
|
|
|
|
|
|
|
### 4.3 共识算法对比
|
|
|
|
|
|
|
|
|
|
|
|
| 算法 | 提出时间 | 可理解性 | 使用系统 |
|
|
|
|
|
|
|------|---------|---------|---------|
|
|
|
|
|
|
| Paxos | 1990 | 困难 | Google Chubby |
|
|
|
|
|
|
| Raft | 2014 | 容易 | etcd、Consul、TiKV |
|
|
|
|
|
|
| ZAB | 2011 | 中等 | ZooKeeper |
|
|
|
|
|
|
| EPaxos | 2013 | 困难 | 学术研究为主 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 分布式事务:跨节点的"全有或全无"
|
|
|
|
|
|
|
|
|
|
|
|
单机数据库的事务靠本地锁和日志就能实现 ACID。但当一个业务操作涉及多个服务/数据库时,如何保证原子性?
|
|
|
|
|
|
|
|
|
|
|
|
### 5.1 两阶段提交(2PC)
|
|
|
|
|
|
|
|
|
|
|
|
最经典的分布式事务协议,分为两个阶段:
|
|
|
|
|
|
|
|
|
|
|
|
| 阶段 | 协调者动作 | 参与者动作 |
|
|
|
|
|
|
|------|-----------|-----------|
|
|
|
|
|
|
| Prepare | 问所有参与者"能提交吗?" | 执行操作但不提交,回复 Yes/No |
|
|
|
|
|
|
| Commit | 如果全部 Yes,发送 Commit | 正式提交;如果有 No,全部回滚 |
|
|
|
|
|
|
|
|
|
|
|
|
**2PC 的问题**:
|
|
|
|
|
|
- **阻塞**:Prepare 后如果协调者挂了,参与者会一直等待
|
|
|
|
|
|
- **单点故障**:协调者是单点,挂了整个事务卡住
|
|
|
|
|
|
- **性能差**:需要多次网络往返,锁持有时间长
|
|
|
|
|
|
|
|
|
|
|
|
### 5.2 Saga 模式
|
|
|
|
|
|
|
|
|
|
|
|
Saga 把一个大事务拆成多个本地事务,每个本地事务有对应的补偿操作。如果某一步失败,就逆序执行补偿。
|
|
|
|
|
|
|
|
|
|
|
|
**电商下单的 Saga 示例**:
|
|
|
|
|
|
|
|
|
|
|
|
| 步骤 | 正向操作 | 补偿操作 |
|
|
|
|
|
|
|------|---------|---------|
|
|
|
|
|
|
| T1 | 创建订单(待支付) | 取消订单 |
|
|
|
|
|
|
| T2 | 扣减库存 | 恢复库存 |
|
|
|
|
|
|
| T3 | 扣减余额 | 退还余额 |
|
|
|
|
|
|
| T4 | 确认订单(已支付) | — |
|
|
|
|
|
|
|
|
|
|
|
|
如果 T3(扣减余额)失败:执行 C2(恢复库存)→ C1(取消订单)。
|
|
|
|
|
|
|
|
|
|
|
|
**两种编排方式**:
|
|
|
|
|
|
- **编排式(Choreography)**:每个服务监听事件,自行决定下一步。简单但难以追踪全局状态
|
|
|
|
|
|
- **协调式(Orchestration)**:有一个中心协调者控制流程。清晰但协调者是单点
|
|
|
|
|
|
|
|
|
|
|
|
### 5.3 TCC(Try-Confirm-Cancel)
|
|
|
|
|
|
|
|
|
|
|
|
TCC 是 2PC 的业务层实现,把每个操作分为三个阶段:
|
|
|
|
|
|
|
|
|
|
|
|
| 阶段 | 说明 | 示例(扣库存) |
|
|
|
|
|
|
|------|------|---------------|
|
|
|
|
|
|
| Try | 预留资源,但不真正执行 | 冻结 10 件库存(可用库存 -10,冻结库存 +10) |
|
|
|
|
|
|
| Confirm | 确认执行,消耗预留资源 | 冻结库存 -10(真正扣减) |
|
|
|
|
|
|
| Cancel | 取消预留,释放资源 | 冻结库存 -10,可用库存 +10(恢复) |
|
|
|
|
|
|
|
|
|
|
|
|
### 5.4 三种方案对比
|
|
|
|
|
|
|
|
|
|
|
|
| 方案 | 一致性 | 性能 | 复杂度 | 适用场景 |
|
|
|
|
|
|
|------|--------|------|--------|---------|
|
|
|
|
|
|
| 2PC | 强一致 | 低 | 中 | 数据库层面的跨库事务 |
|
|
|
|
|
|
| Saga | 最终一致 | 高 | 高 | 长流程业务(订单、物流) |
|
|
|
|
|
|
| TCC | 最终一致 | 中 | 最高 | 资金类高可靠场景 |
|
|
|
|
|
|
|
|
|
|
|
|
::: tip 实际选择建议
|
|
|
|
|
|
- 能用单库事务就不要用分布式事务
|
|
|
|
|
|
- 大多数业务场景用 Saga + 消息队列就够了
|
|
|
|
|
|
- TCC 适合对一致性要求极高的金融场景,但开发成本很高
|
|
|
|
|
|
- 2PC 适合数据库中间件(如 ShardingSphere)自动处理
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 总结
|
|
|
|
|
|
|
|
|
|
|
|
分布式系统是现代互联网的基础设施,但它的复杂性远超单机系统。理解这些挑战不是为了"解决"它们(很多是根本性的),而是为了在设计系统时做出正确的权衡。
|
|
|
|
|
|
|
|
|
|
|
|
回顾本章的关键要点:
|
|
|
|
|
|
|
|
|
|
|
|
1. **CAP 定理**:网络分区不可避免,实际选择是在一致性和可用性之间权衡
|
|
|
|
|
|
2. **一致性模型**:从强一致到最终一致是一个光谱,根据业务需求选择
|
|
|
|
|
|
3. **八大挑战**:网络不可靠、时钟不同步、网络分区、脑裂等相互关联
|
|
|
|
|
|
4. **共识算法**:Raft 是目前最实用的共识算法,etcd/Consul 都基于它
|
|
|
|
|
|
5. **分布式事务**:Saga 适合大多数场景,TCC 适合金融场景,2PC 适合数据库层
|
|
|
|
|
|
|
|
|
|
|
|
## 延伸阅读
|
|
|
|
|
|
|
|
|
|
|
|
- [Designing Data-Intensive Applications](https://dataintensive.net/) - Martin Kleppmann 的分布式系统经典
|
|
|
|
|
|
- [The Raft Consensus Algorithm](https://raft.github.io/) - Raft 官方可视化演示
|
|
|
|
|
|
- [CAP Twelve Years Later](https://www.infoq.com/articles/cap-twelve-years-later-how-the-rules-have-changed/) - Brewer 对 CAP 的重新审视
|
|
|
|
|
|
- [Jepsen](https://jepsen.io/) - 分布式系统正确性测试框架
|
|
|
|
|
|
- [分布式系统模式](https://martinfowler.com/articles/patterns-of-distributed-systems/) - Martin Fowler 的分布式模式合集
|