01.不可靠的分布式系统

不可靠的分布式系统

传统集中式的系统,譬如单个计算机上的软件,当硬件正常工作时,相同的操作总是产生相同的结果(即保证了确定性);如果存在硬件问题(例如,内存损坏或连接器松动),其后果通常是整个系统故障(例如,内核崩溃,蓝屏死机,启动失败)。此类系统通常要么功能完好,要么完全失效,而不是介于两者之间;很多时候如果发生内部错误,我们宁愿电脑完全崩溃,而不是返回难以处理的错误的结果,此类系统我们也往往认为其是稳定的。

在分布式系统中,我们不再处于理想化的系统模型中,它与运行在单台计算机上的程序的不同之处在于:没有共享内存,只有通过可变延迟的不可靠网络传递的消息;系统可能遭受部分失效;不可靠的时钟和处理暂停。譬如单个数据中心(DC)中长期存在的网络分区,配电单元 PDU 故障,交换机故障,整个机架的意外重启,整个数据中心主干网络故障,整个数据中心的电源故障,乃至于光缆被挖断等等。在分布式系统中,尽管系统的其他部分工作正常,但系统的某些部分可能会以某种不可预知的方式被破坏。这被称为部分失效(partial failure)。难点在于部分失效是不确定性的(nonderterministic):如果你试图做任何涉及多个节点和网络的事情,它有时可能会工作,有时会出现不可预知的失败。正如我们将要看到的,你甚至不知道是否成功了,因为消息通过网络传播的时间也是不确定的。

NPC 问题

在分布式系统中,最典型的问题可以归纳为所谓的 NPC 问题,即 Network Delay, Process Pause, Clock Drift 的首字母缩写:

  • Network Delay,网络延迟,当您尝试通过网络发送数据包时,数据包可能会丢失或任意延迟。同样,答复可能会丢失或延迟,所以如果你没有得到答复,你不知道消息是否通过。虽然网络在多数情况下工作的还可以,虽然TCP 保证传输顺序和不会丢失,但它无法消除网络延迟问题。一个糟糕的例子是:客户正紧张的坐在屏幕前等待下单结果,服务器也已下单成功,但在返回的确认响应在网络上迷失了,也就是走丢了。

  • Process Pause,进程暂停,一个进程可能会在其执行的任何时候暂停一段相当长的时间,被其他节点宣告死亡,然后再次复活,却没有意识到它被暂停了。有很多种原因可以导致进程暂停:比如编程语言中的 GC(垃圾回收机制)会暂停所有正在运行的线程;再比如,我们有时会暂停云服务器,从而可以在不重启的情况下将云服务器从一台主机迁移到另一台主机。我们无法确定性预测进程暂停的时长,你以为持续几百毫秒已经很长了,但实际上持续数分钟之久进程暂停并不罕见。

  • Clock Drift,时钟漂移。现实生活中我们通常认为时间是平稳流逝,单调递增的,但在计算机中不是。计算机使用时钟硬件计时,通常是石英钟,计时精度有限,同时受机器温度影响。为了在一定程度上同步网络上多个机器之间的时间,通常使用 NTP 协议将本地设备的时间与专门的时间服务器对齐,这样做的一个直接结果是设备的本地时间可能会突然向前或向后跳跃

NPC 问题速览

分布式系统中的抽象

分布式系统中的许多事情可能会出错。处理这种故障的最简单方法是简单地让整个服务失效,并向用户显示错误消息。如果无法接受这个解决方案,我们就需要找到容错的方法,即使某些内部组件出现故障,服务也能正常运行。不过在前文我们讨论的所有问题都发生的情况下:网络中的数据包可能会丢失,重新排序,重复递送或任意延迟;时钟只是尽其所能地近似;且节点可以暂停(例如,由于垃圾收集)或随时崩溃,我们需要找到一些带有实用保证的通用抽象,仅实现一次而后让应用依赖这些保证,最终构建我们期望的容错系统。

典型的抽象就是事务与共识,通过使用事务,应用可以假装没有崩溃(原子性),没有其他人同时访问数据库(隔离),存储设备是完全可靠的(持久性)。即使发生崩溃,竞态条件和磁盘故障,事务抽象隐藏了这些问题,因此应用不必担心它们。分布式系统的设计核心之一就在一致性的实现和妥协,我们需要选择合适的算法来保证不同节点之间的通信和数据达到无限趋向一致性。实际情况下,保证不同节点在充满不确定性网络环境下能达成相同副本的一致性是非常困难的,无法保证网络的正常连接和信息的传送,于是发展出了 CAP/FLP/DLS 这三个重要的理论:

  • CAP: 分布式计算系统不可能同时确保一致性(Consistency)、可用性(Availablity)和分区容忍性(Partition)。
  • FLP: 在异步环境中,如果节点间的网络延迟没有上限,只要有一个恶意的节点存在,就没有算法能在有限的时间内达成共识。
  • DLS: 网络延时可以保证小于已知时间的同步模型中的协议可以 100% 容错,网络延时有界限但是我们并不知道在哪里的部分同步网络模型可以容忍拜占庭错误,异步模型中的确定性的协议(没有网络延时上限)不能容错。