数据密集型应用系统设计-第七章分布式系统的麻烦-笔记


这阵子在看数据密集型应用系统设计书籍,自己把书籍比较重要的内容整理出来,基本一天一更,请感兴趣的朋友多多关注! 整个系列会在这几天都发布出来,可以关注一下

链接: 数据密集型应用系统设计-笔记.


第八章 分布式系统的麻烦

使用分布式系统与在一台计算机上编写软件有着根本的区别,主要的区别在于,有许多新颖和刺激的方法可以使事情出错。在这一章中,我们将了解实践中出现的问题,理解我们能够依赖,和不可以依赖的东西。

1 故障与部分失效

在分布式系统中,尽管系统的其他部分工作正常,但系统的某些部分可能会以某种不可预知的方式被破坏。这被称为部分失效(partial failure)。难点在于部分失效是不确定性的(nonderterministic):如果你试图做任何涉及多个节点和网络的事情,它有时可能会工作,有时会出现不可预知的失败。正如我们将要看到的,你甚至不知道是否成功了,因为消息通过网络传播的时间也是不确定的!

1.1 云计算与超级计算机

  • 构建大型计算系统有不同的方式
    • 一个极端是高性能计算(HPC)领域。具有数千个CPU的超级计算机通常用于计算密集型科学计算任务,如天气预报或分子动力学(模拟原子和分子的运动)。
    • 另一个极端是云计算(cloud computing),云计算并不是一个良好定义的概念,但通常与多租户数据中心,连接IP网络(通常是以太网)的商用计算机,弹性/按需资源分配以及计量计费等相关联。
    • 传统企业数据中心位于这两个极端之间。
  • 因此也有着不同的故障处理方式
    • 在超级计算机中,作业通常会不时地会将计算的状态存盘到持久存储中。如果一个节点出现故障,通常的解决方案是简单地停止整个集群的工作负载。故障节点修复后,计算从上一个检查点重新开始。因此,超级计算机更像是一个单节点计算机而不是分布式系统:通过让部分失败升级为完全失败来处理部分失败——如果系统的任何部分发生故障,只是让所有的东西都崩溃(就像单台机器上的内核恐慌一样)
    • 超级计算机通常由专用硬件构建而成,每个节点相当可靠,节点通过共享内存和远程直接内存访问(RDMA) 进行通信。另一方面,云服务中的节点是由商用机器构建而成的,由于规模经济,可以以较低的成本提供相同的性能,而且具有较高的故障率。
    • 纠错码允许数字数据在通信信道上准确传输,偶尔会出现一些错误,例如由于无线网络上的无线电干扰
    • 互联网协议(Internet Protocol, IP) 不可靠:可能丢弃,延迟,重复或重排数据包。 传输控制协议(Transmission Control Protocol, TCP)在互联网协议(IP)之上提供了更可靠的传输层:它确保丢失的数据包被重新传输,消除重复,并且数据包被重新组装成它们被发送的顺序。

2 不可靠的网络

  • 为什么需要网络:本书中关注的分布式系统是无共享的系统,即通过网络连接的一堆机器。网络是这些机器可以通信的唯一途径——我们假设每台机器都有自己的内存和磁盘,一台机器不能访问另一台机器的内存或磁盘(除了通过网络向服务器发出请求)。

  • 无共享并不是构建系统的唯一方式,但它已经成为构建互联网服务的主要方式,其原因如下:相对便宜,因为它不需要特殊的硬件,可以利用商品化的云计算服务,通过跨多个地理分布的数据中心进行冗余可以实现高可靠性。

在这里插入图片描述

  • 网络通信过程中可能出现的错误

    1. 请求可能已经丢失(可能有人拔掉了网线)。
    2. 请求可能正在排队,稍后将交付(也许网络或接收方过载)。
    3. 远程节点可能已经失效(可能是崩溃或关机)。
    4. 远程节点可能暂时停止了响应(可能会遇到长时间的垃圾回收暂停;),但稍后会再次响应。
    5. 远程节点可能已经处理了请求,但是网络上的响应已经丢失(可能是网络交换机配置错误)。
    6. 远程节点可能已经处理了请求,但是响应已经被延迟,并且稍后将被传递(可能是网络或者你自己的机器过载)。
  • 网络错误的难题:发送者甚至不能分辨数据包是否被发送:唯一的选择是让接收者发送响应消息,这可能会丢失或延迟。这些问题在异步网络中难以区分:您所拥有的唯一信息是,您尚未收到响应。如果您向另一个节点发送请求并且没有收到响应,则不可能判断是什么原因。

  • 解决方案:超时(Timeout),在一段时间之后放弃等待,并且认为响应不会到达。但是,当发生超时时,你仍然不知道远程节点是否收到了请求(如果请求仍然在某个地方排队,那么即使发送者已经放弃了该请求,仍然可能会将其发送给接收者)。

2.1 检测故障

网络的不确定性使得很难判断一个节点是否工作。在某些特定的情况下,您可能会收到一些反馈信息,明确告诉您某些事情没有成功:

  • 如果可以连接到运行节点的机器,但没有进程正在侦听目标端口(例如,因为进程崩溃),操作系统将通过发送FIN或RST来关闭并重用TCP连接。但是,如果节点在处理请求时发生崩溃,则无法知道远程节点实际处理了多少数据。
  • 如果节点进程崩溃(或被管理员杀死),但节点的操作系统仍在运行,则脚本可以通知其他节点有关该崩溃的信息,以便另一个节点可以快速接管,而无需等待超时到期,HBase就是这么做的。
  • 如果有权访问数据中心网络交换机的管理界面,则可以通过它们检测硬件级别的链路故障(例如,远程机器是否关闭电源)。如果您通过互联网连接,或者如果您处于共享数据中心而无法访问交换机,或者由于网络问题而无法访问管理界面,则排除此选项。
  • 如果路由器确认您尝试连接的IP地址不可用,则可能会使用ICMP目标不可达数据包回复。但是,路由器不具备神奇的故障检测能力——它受到与网络其他参与者相同的限制。

关于远程节点关闭的快速反馈很有用,但是你不能指望它。即使TCP确认已经传送了一个数据包,应用程序在处理之前可能已经崩溃。如果你想确保一个请求是成功的,你需要应用程序本身的正确响应

2.2 超时与无穷延迟

  • 超时等待时间:短的超时可以更快地检测到故障,但有更高地风险误将一个节点宣布为失效,而该节点实际上只是暂时地变慢了(例如由于节点或网络上的负载峰值)
  • 节点超时后需要做什么:当一个节点被宣告死亡时,它的职责需要转移到其他节点,这会给其他节点和网络带来额外的负担。
  • 特殊情况:如果系统已经处于高负荷状态,则过早宣告节点死亡会使问题更严重。特别是如果节点实际上没有死亡,只是由于过载导致其响应缓慢;这时将其负载转移到其他节点可能会导致级联失效(cascading failure)(在极端情况下,所有节点都宣告对方死亡,所有节点都将停止工作)。
  • 超时时间的设置2d + r:设想一个虚构的系统,其网络可以保证数据包的最大延迟——每个数据包要么在一段时间内传送,要么丢失,但是传递永远不会比d更长。此外,假设你可以保证一个非故障节点总是在一段时间内处理一个请求r。在这种情况下,您可以保证每个成功的请求在2d + r时间内都能收到响应,如果您在此时间内没有收到响应,则知道网络或远程节点不工作
  • 实际情况:异步网络具有无限的延迟(即尽可能快地传送数据包,但数据包到达可能需要的时间没有上限),并且大多数服务器实现并不能保证它们可以在一定的最大时间内处理请求。

2.3 同步网络与异步网络

网络拥堵有以下几种情况:

  • 网络拥塞:如果多个不同的节点同时尝试将数据包发送到同一目的地,则网络交换机必须将它们排队并将它们逐个送入目标网络链路。在繁忙的网络链路上,数据包可能需要等待一段时间才能获得一个插槽。如果传入的数据太多,交换机队列填满,数据包将被丢弃,因此需要重新发送数据包 - 即使网络运行良好。
  • 操作系统层面排队:当数据包到达目标机器时,如果所有CPU内核当前都处于繁忙状态,则来自网络的传入请求将被操作系统排队,直到应用程序准备好处理它为止。根据机器上的负载,这可能需要一段任意的时间。
  • 虚拟机监视器排队:在虚拟化环境中,正在运行的操作系统经常暂停几十毫秒,因为另一个虚拟机正在使用CPU内核。在这段时间内,虚拟机不能从网络中消耗任何数据,所以传入的数据被虚拟机监视器排队(缓冲),进一步增加了网络延迟的可变性。
  • TCP执行流量控制(flow control):(也称为拥塞避免(congestion avoidance)背压(backpressure)),其中节点会限制自己的发送速率以避免网络链路或接收节点过载。这意味着甚至在数据进入网络之前,在发送者处就需要进行额外的排队。

为什么是互联网使用分组交互,而不是像电话那边使用电路传输,而电路传输有个好处就是能有一个保证的最大往返时间

  • 针对突发流量的优化。一个电路适用于音频或视频通话,在通话期间需要每秒传送相当数量的比特。但请求网页,发送电子邮件或传输文件没有任何特定的带宽要求——我们只是希望它尽快完成。
  • 如果想通过电路传输文件,你得预测一个带宽分配。猜的太低,传输速度会不必要的太慢,导致网络容量闲置。猜的太高,电路就无法建立(因为如果无法保证其带宽分配,网络不能建立电路)。因此,将电路用于突发数据传输会浪费网络容量,并且使传输不必要地缓慢。相比之下,TCP动态调整数据传输速率以适应可用的网络容量。

我们可以预测网络延迟吗

  • 当前部署的技术不允许我们对网络的延迟或可靠性作出任何保证:我们必须假设网络拥塞,排队和无限的延迟总是会发生。因此,超时时间没有“正确”的值——它需要通过实验来确定。
  • 可以将延迟变化视为动态资源分区的结果
    • 电路传输(静态分区):假设两台电话交换机之间有一条线路,可以同时进行10,000个呼叫。通过此线路切换的每个电路都占用其中一个呼叫插槽。即使你现在是电话上唯一的电话,并且所有其他9,999个插槽都未使用,您的电路仍将分配与导线充分利用时相同的固定数量的带宽。
    • 分组传输(动态分区)
      • 互联网动态分享网络带宽的方式。发送者互相推挤和争夺,以让他们的数据包尽可能快地通过网络,并且网络交换机决定从一个时刻到另一个时刻发送哪个分组(即,带宽分配)。这种方法有排队的缺点,但其优点是它最大限度地利用了电线。电线固定成本,所以如果你更好地利用它,你通过电线发送的每个字节都会更便宜。
      • 类似CPU:如果在多个线程间动态共享每个CPU内核,则一个线程有时必须在操作系统的运行队列里等待,而另一个线程正在运行,这样每个线程都有可能被暂停一个不定的时间长度。但是,与为每个线程分配静态数量的CPU周期相比,这会更好地利用硬件。更好的硬件利用率也是使用虚拟机的重要动机。
      • 如果资源是静态分区的(如专用硬件和专用带宽分配),则在某些环境中可以实现延迟保证。但是,这是以降低利用率为代价的,是更昂贵的。另一方面,动态资源分配的多租户提供了更好的利用率,所以它更便宜,但它具有可变延迟的缺点。

3 不可靠的时钟

时钟很重要,在各个应用都起着重要的作用

  • 判断请求超时
  • 计算响应时间,服务耗时等
  • 定时操作
  • 判断缓存过期
  • 记录操作时间

分布式系统钟,由于通信不是即时的:消息通过网络从一台机器传送到另一台机器需要时间。收到消息的时间总是晚于发送的时间,但是由于网络中的可变延迟,我们不知道晚了多少时间。这个事实导致有时很难确定在涉及多台机器时发生事情的顺序。并且由于每台机器都有自己的时钟,这些设备不是完全准确的,所以每台机器都有自己的时间概念,可能比其他机器稍快或更慢。所以需要找个同步机器的方式,最常用的机制是网络时间协议(NTP),它允许根据一组服务器报告的时间来调整计算机时钟。服务器则从更精确的时间源(如GPS接收机)获取时间。

3.1 单调钟与日历时钟

现代计算机至少有两种不同的时钟:日历时钟(time-of-day clock)和单调钟(monotonic clock)。尽管它们都衡量时间,但区分这两者很重要,因为它们有不同的目的。

3.1.1 日历时钟

定义:日历时钟是根据某个日历(也称为挂钟时间(wall-clock time))返回当前日期和时间。例如,Linux上的clock_gettime(CLOCK_REALTIME)[^v]和Java中的System.currentTimeMillis()返回自epoch(UTC时间1970年1月1日午夜)以来的秒数(或毫秒),根据公历(Gregorian)日历,不包括闰秒。有些系统使用其他日期作为参考点。

同步:日历时钟通常与NTP同步,理想情况下使得一台机器的时间戳与另一台机器上的时间戳相同。但是实际情况,如果本地时钟在NTP服务器之前太远,则它可能会被强制重置,看上去好像跳回了先前的时间点。这些跳跃以及他们经常忽略闰秒的事实,使日历时钟不能用于测量经过时间(elapsed time)

NTP原理

  • 由RFC1305定义的时间同步协议,使用NTP的目的是对网络内所有具有时钟的设备进行时钟同步,使网络内所有设备的时钟保持一致,从而使设备能够提供基于统一时间的多种应用,用来在分布式时间服务器和客户端之间进行时间同步

  • NTP基于UDP报文进行传输,使用的UDP端口号为123

  • 时钟同步过程

    img

    • (1)Device A发送一个NTP报文给Device B,该报文带有它离开Device A时的时间戳,该时间戳为10:00:00am(T1)
    • (2)当此NTP报文到达Device B时,Device B加上自己的时间戳,该时间戳为11:00:01am(T2)
    • (3)当此NTP报文离开Device B时,Device B再加上自己的时间戳,该时间戳为11:00:02am(T3)
    • (4)当Device A接收到该响应报文时,Device A的本地时间为10:00:03am(T4)
    • (5)至此,Device A已经拥有足够的信息来计算两个重要的参数:NTP报文的往返时延Delay=(T4-T1)-(T3-T2)=2秒
    • (6)Device A就能够根据这些信息来设定自己的时钟,使之与Device B的时钟同步
  • NTP报文格式

img

  • LI(Leap Indicator):长度为2比特,值为“11”时表示告警状态,时钟未被同步。为其他值时NTP本身不做处理。

  • VN(Version Number):长度为3比特,表示NTP的版本号,目前的最新版本为3。

  • Mode:长度为3比特,表示NTP的工作模式。不同的值所表示的含义分别是:0未定义、1表示主动对等体模式、2表示被动对等体模式、3表示客户模式、4表示服务器模式、5表示广播模式或组播模式、6表示此报文为NTP控制报文、7预留给内部使用。

    • 客户端/服务器模式:在客户端/服务器模式中,客户端向服务器发送时钟同步报文,报文中的Mode字段设置为3(客户模式)。服务器端收到报文后会自动工作在服务器模式,并发送应答报文,报文中的Mode字段设置为4(服务器模式)。客户端收到应答报文后,进行时钟过滤和选择,并同步到优选的服务器。在该模式下,客户端能同步到服务器,而服务器无法同步到客户端。

      img

    • 对等体模式:在对等体模式中,主动对等体和被动对等体之间首先交互Mode字段为3(客户端模式)和4(服务器模式)的NTP报文。之后,主动对等体向被动对等体发送时钟同步报文,报文中的Mode字段设置为1(主动对等体),被动对等体收到报文后自动工作在被动对等体模式,并发送应答报文,报文中的Mode字段设置为2(被动对等体)。经过报文的交互,对等体模式建立起来。主动对等体和被动对等体可以互相同步。如果双方的时钟都已经同步,则以层数小的时钟为准

      img

    • 广播模式:在广播模式中,服务器端周期性地向广播地址255.255.255.255发送时钟同步报文,报文中的Mode字段设置为5(广播模式)。客户端侦听来自服务器的广播报文。当客户端接收到第一个广播报文后,客户端与服务器交互Mode字段为3(客户模式)和4(服务器模式)的NTP报文,以获得客户端与服务器间的网络延迟。之后,客户端就进入广播客户端模式,继续侦听广播报文的到来,根据到来的广播报文对系统时钟进行同步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值