分布式系统的复杂度从哪来

61 阅读 2034 字 · 约 7 分钟

把三台机器放在一起,不等于就有了分布式系统。真正的分布式系统,是让多台机器协同完成一件事——而这件事的复杂度,恰好来自「协同」二字。

为什么单机到多机不是简单的数量变化?因为单机上一切井然有序:数据在同一个内存空间,时钟只有一个,锁一把就够。一旦跨了机器,这三样全部失效。

分布式系统的所有复杂度,可以归结为三个根本问题:空间、时间、共识

分布式系统的复杂度来自三个根本问题:空间、时间、共识——空间最直观,时间更隐蔽,共识是叠加后的终极挑战

空间:数据不在同一个地方

单机里,两个函数共享一个变量,修改立即可见。分布式系统里,数据分散在多台机器上,每台机器只持有「部分的真相」。

状态分散带来的第一个问题是 复制(Replication)。你需要在多个节点上维护同一份数据的副本——问题是,谁来写?如果所有节点都能写,冲突怎么解决?于是有了主从复制(single-leader)、多主复制(multi-leader)、无主复制(leaderless)三种模式,各有各的权衡。

第二个问题是 分区(Partitioning)。数据量大到单个节点放不下时,你不得不把数据切成片段分布到不同节点上。怎么切?按 key 范围(range sharding)还是按哈希(hash sharding)?切完之后,跨分区的查询怎么路由?数据倾斜了怎么再平衡?

复制和分区各自解决一个问题,但放在一起会互相放大:每个分区可能需要自己的复制策略,节点角色(主/从)需要与分区拓扑协调。这就是「状态分散」的代价。

时间:先后顺序不再天经地义

单机上,代码执行顺序就是时间顺序。a = 1b = a + 1 之前,这是铁律。

分布式系统里没有全局时钟。两台机器的本地时钟不可能完全同步(NTP 也就毫秒级精度),更重要的是——消息在网络中的到达顺序不保证。你无法通过「看时间戳」来判断两个事件谁先谁后。

为此,Leslie Lamport 在 1978 年提出了 逻辑时钟(Lamport Timestamps):不关心墙上时间,只关心事件的 happens-before 关系。但单一的逻辑时钟只能给出偏序(partial order),不能区分并发和因果。于是有了 向量时钟(Vector Clocks),每个节点维护一个向量,记录「我看到别人做了多少步」,能精确判断任意两个事件的因果关系。

时间的不确定性直接导致了 一致性模型 的光谱:从最强的线性一致性(Linearizability,所有操作看起来瞬间完成)到最终一致性(Eventual Consistency,「过一阵子总能一致」),中间还有顺序一致性(Sequential Consistency)、因果一致性(Causal Consistency)等。它们之间的区别,本质上就是「你愿意为『看起来有序』付出多少代价」。

共识:让一群节点达成一致,难如登天

空间让数据分散,时间让顺序模糊,这两个叠加在一起,引出了分布式系统最难的问题:共识(Consensus)。

共识的形式有很多种面貌:几台机器要选出一个 Leader(领导者选举),一个事务要跨多个数据库原子提交(分布式事务),多个客户端要互斥访问共享资源(分布式锁)。但它们本质上都是同一个问题——让一组互不信任、消息可能延迟或丢失的节点,就某个值达成一致。

FLP 不可能定理(Fischer, Lynch, Paterson, 1985)说了一句残酷的话:在异步系统中,只要有一个节点可能挂掉,确定性共识就不可能。注意——它只说「确定性」共识不可能,没说「概率性」也不行。Paxos 和 Raft 正是利用这一点,用随机超时 + 多数派投票,在工程上做到了足够可靠的共识。

共识协议的经典答案是 Paxos(Lamport, 1989)和 Raft(Ongaro, 2014)。Paxos 正确性毋庸置疑,但出了名的难以理解和实现。Raft 的贡献在于把共识拆成 Leader 选举、日志复制、安全性三个子问题分别处理,可理解性好了一个数量级。Zookeeper 的 ZAB 协议走的也是类似路线,强调顺序保证。

分布式事务则从另一个维度处理共识——不是让节点就一个值达成一致,而是让多个操作要么全成功要么全回滚。2PC(两阶段提交)是最朴素的想法:先问所有人能不能做,再通知所有人做不做。它的问题在于阻塞——协调者挂了,参与者就悬着。3PC 加了一个超时机制,减轻但不根治。Saga 和 TCC 走的是补偿路线:把一个大事务拆成小步骤,失败了反向补偿,牺牲了隔离性换取了可用性。

三个支柱是递进的

空间、时间、共识,不是三个平级的概念。空间最直观——「数据不在我这」你马上能感觉到。时间的混乱比空间隐蔽——很多系统看起来是空间问题,查到最后是时钟偏差。共识则是空间和时间叠加后的终极挑战——正因为数据分散、消息不可靠,才需要如此复杂的协议来让多个节点达成一致。

理解了这三个支柱,再回头看分布式系统里那些眼花缭乱的技术——Raft、向量时钟、Saga、一致性哈希、领导者选举——它们就不再是孤立的招式,而是围绕同一个问题展开的不同回答。那个问题是:多台机器要协同完成一件事,但每台机器只能看到自己的局部状态。