Skip to content

分布式系统的挑战

前言

当一台机器不够用时,问题才真正开始。 分布式系统是现代互联网的基石——从微信消息到淘宝下单,背后都是成百上千台机器协同工作。但"分布式"不是免费的午餐,它带来了一系列单机系统从未遇到的挑战。

这篇文章会带你学什么?

学完这章后,你将获得:

  • 核心定理:理解 CAP 定理及其对系统设计的影响
  • 一致性模型:区分强一致性、最终一致性、因果一致性
  • 八大挑战:掌握分布式系统面临的核心难题
  • 共识算法:了解 Paxos、Raft 等分布式共识的基本思想
  • 实战模式:熟悉 2PC、Saga、CRDT 等常用解决方案
章节内容核心概念
第 1 章为什么需要分布式扩展性、可用性、地理分布
第 2 章CAP 定理一致性、可用性、分区容错
第 3 章一致性模型强一致、最终一致、因果一致
第 4 章八大挑战网络、时钟、分区、脑裂等
第 5 章共识算法Paxos、Raft、ZAB
第 6 章分布式事务2PC、Saga、TCC

0. 全景图:为什么需要分布式系统?

单机系统简单可靠,但有三个无法逾越的瓶颈:

瓶颈说明分布式的解法
性能上限单机 CPU、内存、磁盘有物理极限水平扩展:加更多机器分担负载
单点故障一台机器挂了,整个服务就挂了冗余副本:多台机器互为备份
地理延迟用户在全球各地,单机只能在一个地方多地部署:就近服务用户

分布式的代价

分布式系统解决了上面的问题,但引入了新的复杂性:网络不可靠、时钟不同步、部分失败、数据一致性……这些就是本文要讨论的"挑战"。

Peter Deutsch 的分布式计算八大谬误告诉我们,以下假设在分布式环境中都是错的:

  1. 网络是可靠的
  2. 延迟是零
  3. 带宽是无限的
  4. 网络是安全的
  5. 拓扑不会变化
  6. 只有一个管理员
  7. 传输成本是零
  8. 网络是同构的

1. CAP 定理:分布式系统的"不可能三角"

2000 年,Eric Brewer 提出了 CAP 猜想(后被证明为定理):一个分布式系统最多只能同时满足以下三个属性中的两个。

属性含义通俗理解
Consistency(一致性)所有节点在同一时刻看到相同的数据你在任何 ATM 查余额,结果都一样
Availability(可用性)每个请求都能收到非错误的响应系统永远能回应你,不会说"服务不可用"
Partition tolerance(分区容错)网络分区时系统仍能继续运行即使部分网线断了,系统还能工作
CAP 定理交互演示
点击选择两个属性,查看对应的系统类型
C
一致性
所有节点看到相同的数据
A
可用性
每个请求都能得到响应
P
分区容错
网络分区时系统仍能运行
请选择两个属性查看结果

为什么只能选两个?

在分布式环境中,网络分区(P)是不可避免的——光纤会被挖断、交换机会故障、数据中心会断网。所以 P 是必选项,实际的选择是在 C 和 A 之间权衡:

  • 选 CP:分区时拒绝不确定的请求,保证数据正确 → 适合金融、库存
  • 选 AP:分区时继续服务,但数据可能暂时不一致 → 适合社交、内容

CAP 不是非黑即白

现实中的系统不是简单的"CP 或 AP"。很多系统在不同操作上做不同的选择——比如同一个数据库,读操作可以是 AP(允许读旧数据),写操作可以是 CP(要求多数确认)。


2. 一致性模型:数据同步的"严格程度"

一致性不是一个开关(有或没有),而是一个光谱。不同的一致性模型在"正确性"和"性能"之间做不同的权衡。

一致性模型对比
点击查看不同一致性模型的行为差异
强一致性
最终一致性
因果一致性
强一致性
写入成功后,所有节点立即返回最新值。像单机数据库一样的体验。
T1
节点A
v1
节点B
v1
节点C
v1
初始状态,所有节点数据一致
T2
节点A
v2 ✍️
节点B
同步中...
节点C
同步中...
客户端写入 v2,等待所有节点确认
T3
节点A
v2
节点B
v2
节点C
v2
所有节点确认后才返回成功,读任意节点都是 v2
权衡:延迟高(需要等所有节点确认),可用性低(节点故障时可能阻塞)

一致性模型对比

模型保证延迟适用场景
强一致性读到的一定是最新写入的值高(需等待同步)银行转账、库存扣减
最终一致性最终所有副本会一致,但中间可能读到旧值低(写入立即返回)社交动态、DNS
因果一致性有因果关系的操作保证顺序中等评论回复、协作编辑
线性一致性所有操作看起来像在单机上按顺序执行最高分布式锁、选主
会话一致性同一会话内保证读到自己的写入低-中用户个人数据

"读己之写"一致性

最常见的实际需求是:用户修改了自己的数据后,自己能立即看到更新(但其他用户可以稍后看到)。这叫"Read Your Own Writes"一致性,是最终一致性的一个实用增强。


3. 八大挑战:分布式系统的"地雷阵"

分布式系统的复杂性不是来自某一个问题,而是多个问题交织在一起。以下是最核心的八大挑战。

分布式系统八大挑战
点击查看每个挑战的详情和应对策略
🔌
网络不可靠
时钟不同步
✂️
网络分区
🔄
数据一致性
💥
部分失败
🧠
脑裂问题
📋
事件排序
🔐
分布式事务
🔌 网络不可靠
分布式系统的节点通过网络通信,而网络随时可能丢包、延迟、断开。这是分布式系统最根本的挑战——你永远不能假设网络是可靠的。
场景举例:服务 A 调用服务 B,请求发出后 3 秒没收到响应。是 B 没收到?还是 B 处理了但响应丢了?A 无法区分。
应对策略:
  • 超时 + 重试:设置合理超时,失败后重试(需保证幂等性)
  • 心跳检测:定期发送心跳包检测连接是否存活
  • 断路器模式:连续失败后暂停调用,避免雪崩

挑战之间的关联

这八大挑战不是孤立的,它们相互关联:

  • 网络不可靠 → 导致 网络分区 → 触发 CAP 权衡
  • 时钟不同步 → 导致 事件排序困难 → 影响 数据一致性
  • 部分失败 → 可能导致 脑裂 → 需要 共识算法 来解决
  • 数据一致性 → 需要 分布式事务 → 但事务又受 网络不可靠 影响

没有银弹

分布式系统没有"完美"的解决方案,只有"合适"的权衡。理解这些挑战的本质,才能在设计系统时做出正确的取舍。


4. 共识算法:如何让多台机器"达成一致"

共识算法是分布式系统的核心——它解决的问题是:多个节点如何就某个值达成一致?即使部分节点故障或网络延迟。

4.1 Paxos

Leslie Lamport 在 1990 年提出,是第一个被严格证明正确的共识算法。

角色职责
Proposer提出提案(值)
Acceptor投票接受或拒绝提案
Learner学习最终被选定的值

两阶段流程

  1. Prepare 阶段:Proposer 发送提案编号,Acceptor 承诺不再接受更小编号的提案
  2. Accept 阶段:Proposer 发送具体值,多数 Acceptor 接受则提案通过

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 共识算法对比

算法提出时间可理解性使用系统
Paxos1990困难Google Chubby
Raft2014容易etcd、Consul、TiKV
ZAB2011中等ZooKeeper
EPaxos2013困难学术研究为主

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最终一致最高资金类高可靠场景

实际选择建议

  • 能用单库事务就不要用分布式事务
  • 大多数业务场景用 Saga + 消息队列就够了
  • TCC 适合对一致性要求极高的金融场景,但开发成本很高
  • 2PC 适合数据库中间件(如 ShardingSphere)自动处理

总结

分布式系统是现代互联网的基础设施,但它的复杂性远超单机系统。理解这些挑战不是为了"解决"它们(很多是根本性的),而是为了在设计系统时做出正确的权衡。

回顾本章的关键要点:

  1. CAP 定理:网络分区不可避免,实际选择是在一致性和可用性之间权衡
  2. 一致性模型:从强一致到最终一致是一个光谱,根据业务需求选择
  3. 八大挑战:网络不可靠、时钟不同步、网络分区、脑裂等相互关联
  4. 共识算法:Raft 是目前最实用的共识算法,etcd/Consul 都基于它
  5. 分布式事务:Saga 适合大多数场景,TCC 适合金融场景,2PC 适合数据库层

延伸阅读