分布式系统(概念、时间、状态)

参考资料:

  1. (CDK5) George Coulouris et al., Distributed Systems Concepts and Design (5th ed.), Addison-Wesley, 2012.
  2. 机工社,金蓓弘老师翻译的《分布式系统 - 概念与设计》
  3. 国科大《分布式与并行计算》课程 PPT

分布式系统

基本概念

分布式计算:是利用分布在网络上的各种软、硬计算机资源进行信息处理的过程,它是通过基于网络的分布式系统实现的。

分布式计算的多种形态:

  • 网格计算、集群计算;
  • 云计算、边缘计算、雾计算;
  • 移动计算、普适计算;
  • 对等计算。

分布式系统:是使得基于网络互相连接的若干计算单元进行协同计算的软件。对用户而言,好像是面对一个单一的系统。

在这里插入图片描述

分布式系统的基本属性:

  • 一个分布式系统拥有一定数目的计算单元和一定数目的进程

    • 物理资源:计算单元

    • 逻辑资源:进程

  • 进程之间通过消息传递进行通信

  • 进程之间以协作的方式交互

  • 通信延迟不可忽略

  • 任何单个逻辑或物理的资源故障不会导致整个系统的崩溃

  • 在资源故障的情况下系统必须具有重新配置和故障恢复的能力

分布式系统的分类:

  • 系统设计的角度
    • 时序假设:同步系统、异步系统、部分同步系统
    • 故障假设:随机故障、非随机故障
    • 进程间的通信机制
  • 使用规模的角度:个人用户、企业用户、互联网应用
  • 基于网络的角度:有线网、无线网;车联网、物联网

在这里插入图片描述

Clouds:云计算

  • IaaS(Infrastructure as a Service)
  • PaaS(Platform as a Service)
  • SaaS(Software as a Service)

在这里插入图片描述

Transaction Processing Systems:事务系统

  • Transaction processing monitor

在这里插入图片描述
Enterprise Application Integration:企业应用集成

  • Communication middleware: remote procedure call (RPC), remote method invocation (RMI), message-oriented middleware, publish / subscribe middleware(发布订阅模式)

在这里插入图片描述

分布式算法与集中式算法的区别:

  1. 分布式算法是以没有全局时钟为前提的,
  2. 没有任何一台机器具有系统的完整状态信息,
  3. 每台机器仅根据本地信息进行决策,
  4. 一台机器出了故障,不会使整个算法崩溃

设计目标

  1. 连接用户和资源:以一种安全、可靠的方式进行资源共享和用户协作

  2. 透明性(Transparency):

    在这里插入图片描述

    • 100% 的透明性并不总是一个好主意,过分强调透明性可能会带来性能效率上的损失
  3. 开放性(Openness):

    • 它提供的服务的规约应该是完整的和中性的,

      • 完整是指实现所需的所有信息都能在服务的接口中指定,
      • 接口的中性描述是指接口的规约并不规定实现是什么样的,

      完整和中性有助于提高互操作能力可移植性

    • 系统应该是灵活的、可扩展 (extensible) 的,

      • 可以把不同开发人员开发的组件搭配起来,配置起来,可以在不影响其它组件的情况下增加、替换组件。
  4. 可伸缩性(Scalability):

    • 规模上可伸缩 / vertical scalability:可以增加更多的用户和资源,
    • 地理上可伸缩 / horizontal scalability:用户、资源都可以相距很远,
    • 管理上可伸缩:能很容易地管理相互独立的组织。

改善系统的可伸缩性:

  • 体系结构层面:
    • 对数据、服务进行克隆
    • 对数据、服务、客户进行拆分,分布到不同地点
  • 通信层面:
    • 使用异步通信,避免信道拥挤
    • 减少通信
  • 容错层面:
    • 隔离故障,避免级联模块的设计,避免单点故障的设计
    • 故障的恢复
  • 数据层面:
    • 使用复制、缓存
    • 尽量实现无状态的系统
    • 如果有状态,尽可能在客户端维护会话,或者使用分布式缓存来存放状态

时间

基本概念

(second):铯原子 Cs133 基态的两个超精细能级间跃迁辐射震荡 9192631770 9192631770 9192631770 周所持续的时间为 1 1 1 秒。

时钟漂移(clock drift):时钟的绝对偏差,石英钟的漂移率为 1 0 − 6 s / s 10^{-6} s \big/ s 106s/s

时钟偏移(clock skew):两个时钟在读数上的瞬时差值

UTC(Universal Time Coordinated):协调世界时,世界标准时间

  • 时间的测量:国家授时中心,使用”小铯钟“。

  • 时间的发送和接收:长波、短波;网络时间服务器;卫星。

计算机时钟

  1. 硬件时钟: H ( t ) H(t) H(t),晶振

  2. 软件时钟: C ( t ) = α H ( t ) + β C(t) = \alpha H(t) + \beta C(t)=αH(t)+β,根据软件调整 ( α , β ) (\alpha,\beta) (α,β) 的值

  3. 分布式系统的每个进程使用各自的本地时间,它们的漂移率各不相同;如果不及时校准,各进程的时钟会偏差很大。

时钟的正确性:设 t < t ′ t<t' t<t 是实际时间, H ( t ) , H ( t ′ ) H(t),H(t') H(t),H(t) 是相应的硬件时钟值, ρ > 0 \rho>0 ρ>0 是漂移率

  • 硬件时钟的误差有界性 ( 1 − ρ ) ( t ′ − t ) ≤ H ( t ′ ) − H ( t ) ≤ ( 1 + ρ ) ( t ′ − t ) (1-\rho)(t'-t) \le H(t')-H(t) \le (1+\rho)(t'-t) (1ρ)(tt)H(t)H(t)(1+ρ)(tt)
  • 软件时钟的单调性 t < t ′ ⇒ C ( t ) < C ( t ′ ) t<t' \Rightarrow C(t) < C(t') t<tC(t)<C(t)
  • 如果计算机时间慢了:在同步点拨快,追上标准时间
  • 如果计算机时间快了:不可拨慢(违反单调性),可以调小 α \alpha α 调大 β \beta β 使得时钟走的慢一些,等候完美时间

时间同步

外部同步:用权威的外部时间源同步进程的时钟

内部同步:指时钟相互同步

  • 内部同步的时钟未必是外部同步的
  • 如果系统在范围 D D D 内是外部同步的,那么同一系统在范围 2 D 2D 2D 内是内部同步的

同步系统

  1. 已知时钟漂移率的范围
  2. 已知最大的消息传输延迟
  3. 已知进程每一步的执行时间

2 2 2 个进程的分布式系统,用 m i n min min 表示最小的消息传输延迟,用 m a x max max 表示最大的消息传输延迟,

  1. 进程 p p p 发送本地时间 t t t 给另一个进程 q q q
  2. 进程 q q q 将自己的时钟设置为 t + ( m i n + m a x ) / 2 t+(min+max)/2 t+(min+max)/2

与实际时间 t + T t r a n s t+T_{trans} t+Ttrans 相差至多 ( m a x − m i n ) / 2 (max-min)/2 (maxmin)/2

N N N 个进程的分布式系统,时间同步算法扩展为:

  1. 进程 p p p 发送当前的本地时间 t = t p t=t_p t=tp 给其他进程 q ≠ p q \neq p q=p
  2. 进程 p p p 等待其他 N − 1 N-1 N1 个进程的消息,设置 s u m = 0 sum=0 sum=0(与自己的时钟偏移)
    1. 收到来自 q q q 的时间 t q t_q tq
    2. 计算 δ = t q + ( m i n + m a x ) / 2 − t p \delta = t_q + (min+max)/2 - t_p δ=tq+(min+max)/2tp(与进程 q q q 的时钟偏移)
    3. 计算累加值 s u m = s u m + δ sum = sum+\delta sum=sum+δ
  3. 当前时间为 t p ′ t_p' tp,将自己的时钟设置为 t p ′ + s u m / N t_p'+sum/N tp+sum/N

系统的 N N N 个计算机,两两之间的时间差至多为 γ < ( m a x − m i n ) / ( 1 − 1 / N ) \gamma < (max-min)/(1-1/N) γ<(maxmin)/(11/N)

异步系统

在进程执行时间、消息传递时间和时钟漂移上没有限制的

  1. 不知道最大的消息传输延迟,可能是无穷大
  2. 但最小的消息传递延迟是可知的

外部同步方法(Cristian 算法):

  1. 使用一个时间服务器 S S S,接收标准时间信号
  2. 进程 p p p 发送给 S S S 一个请求 m r m_r mr
  3. 服务器 S S S 回应消息 m t m_t mt,包含接收到 m r m_r mr 的时间 t t t
  4. 进程 p p p 记录发送 m r m_r mr 和接收 m t m_t mt 之间的往返时间 T r o u n d T_{round} Tround
  5. 进程 p p p 设置时钟为 t + T r o u n d / 2 t+T_{round}/2 t+Tround/2

需要 T r o u n d T_{round} Tround 远小于所要求的时间精度,且时间服务器 S S S 是正确的。由于 t e = t s + T r o u n d t_e = t_s+T_{round} te=ts+Tround t t t 的关系为 t + m i n < t e t+min < t_e t+min<te t > t s + m i n t>t_s+min t>ts+min,因此 t e ∈ [ t + m i n , t + T r o u n d − m i n ] t_e \in [t+min, t+T_{round}-min] te[t+min,t+Troundmin],精度为 ± ( T r o u n d / 2 − m i n ) \pm(T_{round}/2 - min) ±(Tround/2min)

内部同步方法(Berkely 算法):

  1. 在计算机集群里挑选一个 Master,其他的作为 Slave
  2. Master 周期性地轮询,Slave 将自己的时钟值发送给 Master
  3. Master 类似 Cristian 那样观察往返时间,估计 Slave 的本地时间,然后计算所有时间(包括自己)的平均值
  4. Master 发送各个 Slave 需要的调整量给对应的 Slave

精确度取决于 Master-Slave 之间的最大往返时间。为了更强的容错:

  • Master 使用“容错平均值”(差值在一定范围内的子集),过滤掉异常往返时间
  • Master 通过选举产生,这允许 Master 崩溃

网络时间协议(NTP)

NTP(Network Time Protocol)定义了时间服务的体系结构和在 Internet 上发送时间信息的协议。

设计目标:

  • 提供一个服务,使得 Internet 上的用户能精确地同标准时间同步:用统计方法来过滤时序数据

  • 使得客户能经常有效地重新同步以抵消漂移率:该服务具有对大量客户和服务器的可伸缩性

  • 在不可靠的通信链接上提供一个可靠服务:通过提供冗余的服务器以及服务器之间冗余的路径

  • 能防止对时间服务的干扰,无论是恶意的还是偶然的:使用认证技术

体系结构:

  • 主服务器 (在 root 上) 直接连到外部时间源,例如短波时间接收器、GPS接收器之类的设备。层次 (stratum) 2 2 2 的服务器与主服务器同步,层次 3 3 3 的服务器与层次 2 2 2 的服务器同步等等。

  • 同步子网是用 Bellman-Ford 路由算法的变种来组织的,构建以主服务器为根的最小权重的支撑树

在这里插入图片描述

故障处理:

  • 同步子网可以进行重新配置,以应对服务器不可达或出现故障。

  • 如果主服务器的外部时间源出现故障,那么它能变成层次 2 2 2 的二级服务器 。

同步方式:

  • 组播模式,用于高速LAN环境。一个或多个服务器周期性地将时间组播到其他服务器,并设置它们的时钟 (假设延迟很小)。
  • 过程调用模式,类似 Cristian 算法的操作。一个服务器接收来自其他计算机请求,并用时间戳(本地的当前的时钟读数)应答。这个模式适合精确性要求比组播更高的地方,或不能用硬件支持组播的地方。
  • 对称模式,用于在LAN中提供时间信息的服务器和同步子网的较高层(较小的层次数),即要获得最高精确性的地方。一对服务器相互交换有时序信息的消息。

NTP 的消息传递使用 UDP,每个消息携带3个时间戳:

  1. 发送前一个 NTP 消息的本地时间
  2. 接收前一个 NTP 消息的本地时间
  3. 发送当前 NTP 消息的本地时间

在这里插入图片描述

服务器 A A A 发送消息 m m m 给服务器 B B B,发送时间 t i − 3 t_{i-3} ti3 A A A 的),接收时间 t i − 2 t_{i-2} ti2 B B B 的),传输时间为 T T T

服务器 B B B 发送消息 m ′ m' m 给服务器 A A A,发送时间 t i − 1 t_{i-1} ti1 B B B 的),接收时间 t i − 1 t_{i-1} ti1 A A A 的),传输时间为 T ′ T' T

假设服务器 A , B A,B A,B 的时钟真实偏移为 o o o,估计值为 o i o_i oi,令 d i = T + T ′ d_i = T+T' di=T+T,那么
t i − 2 = t i − 3 + t + o t i = t i − 1 + t ′ − o d i = ( t i − 2 − t i − 3 ) + ( t i − t i − 1 ) \begin{aligned} t_{i-2} &= t_{i-3}+t+o\\ t_{i} &= t_{i-1}+t'-o\\ d_i &= (t_{i-2}-t_{i-3}) + (t_{i}-t_{i-1}) \end{aligned} ti2tidi=ti3+t+o=ti1+to=(ti2ti3)+(titi1)

设置估计值 o i = ( t i − 2 − t i − 3 + t i − t i − 1 ) / 2 o_i = (t_{i-2}-t_{i-3} + t_{i}-t_{i-1})/2 oi=(ti2ti3+titi1)/2,那么 o = o i + ( T ′ − T ) / 2 o = o_i + (T'-T)/2 o=oi+(TT)/2,得到 o i − d i / 2 ≤ o ≤ o i + d i / 2 o_i - d_i/2 \le o \le o_i + d_i/2 oidi/2ooi+di/2。因此,各个 NTP 服务器之间应该多次执行程序,使用 d i d_i di 最小的 o i o_i oi 值作为对 o o o 的估计。

逻辑时钟 & 向量时钟

发生在先

Lamport 发生在先(happened-before)关系 → \to ,需要满足:

  • HB1:如果存在进程 p i p_i pi 中的关系 e → i e ′ e \to_i e' eie,那么 e → e ′ e \to e' ee
  • HB2:对于任意的消息 m m m,都有 s e n d ( m ) → r e c e i v e ( m ) send(m) \to receive(m) send(m)receive(m)
  • HB3:如果 e → e ′ e \to e' ee e ′ → e ′ ′ e' \to e'' ee′′,那么 e → e ′ ′ e \to e'' ee′′

发生在先关系的性质:

  1. 不能由 → \to 排序的两个事件( e → e ′ e \to e' ee e ′ → e e' \to e ee 都不成立),它们是并发事件(可能有资源竞争,不是并行),记做 e ∥ e ′ e \| e' ee
  2. 关系 → \to 捕获了以消息传递方式表示的数据流(但不能对非消息传递的数据流动建模)
  3. 关系 → \to 捕获可能的因果关系,第一个事件不一定会影响第二个事件

逻辑时钟

Lamport 逻辑时钟,是一个单调增长的软件计数器。

每个进程 p i p_i pi 维护自己的逻辑时钟 L i L_i Li,用它给事件打时间戳。事件 e e e,用 L i ( e ) L_i(e) Li(e) 表示 p i p_i pi 的时间戳,用 L ( e ) L(e) L(e) 表示任意进程中的时间戳。

计算规则:

  • LC1:进程 p i p_i pi 发出事件 e e e 之前,首先 L i = L i + 1 L_i = L_i+1 Li=Li+1,然后打戳 L i ( e ) L_i(e) Li(e)
  • LC2
    • 发送:进程 p i p_i pi 发送消息 m m m 时,先按照 LC1 打戳,然后在 m m m 上捎带 t = L i t=L_i t=Li
    • 接收:进程 p i p_i pi 接收到 ( m , t ) (m,t) (m,t),先设置 L i = max ⁡ ( L i , t ) L_i = \max(L_i,t) Li=max(Li,t),然后按照 LC1 打戳

逻辑时钟无法区分,是由于局部事件引起的时钟前进,还是由于消息交换引起的时钟前进。

与发生在先的必要不充分关系:

  1. 如果 e → e ′ e \to e' ee,那么 L ( e ) < L ( e ′ ) L(e) < L(e') L(e)<L(e)
  2. 但是 L ( e ) < L ( e ′ ) L(e) < L(e') L(e)<L(e) 不能推出 e → e ′ e \to e' ee

向量时钟

为弥补逻辑时钟的缺点,对于 N N N 个进程,每个进程 p i p_i pi 持有向量 V i [ 1 ⋯ N ] V_i[1 \cdots N] Vi[1N]

  1. V i [ i ] V_i[i] Vi[i] 是进程 p i p_i pi 自己的加时间戳的事件个数(可能与当前事件 e e e 有发生在先关系的的进程 p i p_i pi 上事件个数)
  2. V i [ j ] , j ≠ i V_i[j],j \neq i Vi[j],j=i p j p_j pj 中可能会影响 p i p_i pi 的事件个数(可能与当前事件 e e e 有发生在先关系的进程 p j p_j pj 上事件个数)

计算规则:

  • VC1:初始化 V i [ j ] = 0 ,   ∀ i , j = 1 , ⋯   , N V_i[j]=0,\, \forall i,j=1,\cdots,N Vi[j]=0,i,j=1,,N
  • VC2:进程 p i p_i pi 发出事件 e e e 之前,首先 V i [ i ] = V i [ i ] + 1 V_i[i] = V_i[i]+1 Vi[i]=Vi[i]+1,然后打戳 V i ( e ) V_i(e) Vi(e)
  • VC3:进程 p i p_i pi 发送消息 m m m 时,先按照 VC2 打戳,然后在 m m m 上捎带 t = V i t=V_i t=Vi
  • VC4:进程 p i p_i pi 接收到 ( m , t ) (m,t) (m,t),先设置 V i [ j ] = max ⁡ ( V i [ j ] , t [ j ] ) V_i[j] = \max(V_i[j],t[j]) Vi[j]=max(Vi[j],t[j]),然后按照 VC2 打戳

与发生在先的等价关系:

  1. V = V ′    ⟺    V [ j ] = V ′ [ j ] , ∀ j = 1 , ⋯   , N V = V' \iff V[j] = V'[j],\forall j=1,\cdots,N V=VV[j]=V[j],j=1,,N
  2. V ≤ V ′    ⟺    V [ j ] ≤ V ′ [ j ] , ∀ j = 1 , ⋯   , N V \le V' \iff V[j] \le V'[j],\forall j=1,\cdots,N VVV[j]V[j],j=1,,N
  3. V < V ′    ⟺    ( V ≤ V ′ ) ∧ ( V ≠ V ′ ) V < V' \iff (V \le V') \wedge (V \neq V') V<V(VV)(V=V)
  4. 等价关系: e → e ′    ⟺    V ( e ) < V ( e ′ ) e \to e' \iff V(e) < V(e') eeV(e)<V(e)
  5. 如果 V ( e ) < V ( e ′ ) V(e) < V(e') V(e)<V(e) V ( e ) > V ( e ′ ) V(e) > V(e') V(e)>V(e) 都不成立,那么 e ∥ e ′ e \| e' ee

状态 & 快照

全局状态 & 割集

全局状态:分布式系统可以看作是一系列协同工作的进程集合 P = P 1 , P 2 , … , P n P={P_1,P_2,…,P_n} P=P1P2Pn,进程可以是物理分布的,它们之间通过消息通信实现互操作。分布式系统的全局状态由局部状态集和消息通道状态集组成:

  1. 局部状态集,是指系统中的一个进程的全部变量的集合

  2. 消息通道状态集,是指在消息传输中的消息序列的集合

观察全局状态的必要性:分布式垃圾回收、分布式调试、死锁判定、程序终止判定、检查点。

在这里插入图片描述

一些描述状态的术语:

  • 进程的历史:一系列的内部事件、发送事件、接收事件, h i s t o r y ( p i ) = h i = ⟨ e i 0 , e i 1 , ⋯   ⟩ history(p_i) = h_i = \langle e_i^0,e_i^1,\cdots \rangle history(pi)=hi=ei0,ei1,
  • 进程历史的有限前缀 h i k = ⟨ e i 0 , e i 1 , ⋯   , e i k ⟩ h_i^k = \langle e_i^0,e_i^1,\cdots,e_i^k \rangle hik=ei0,ei1,,eik
  • 全局历史:进程历史的并集, H = ⋃ i = 1 N h i H = \bigcup_{i=1}^N h_i H=i=1Nhi
  • 割集(Cut):全局历史的子集, C = ⋃ i = 1 N h i c i C = \bigcup_{i=1}^N h_i^{c_i} C=i=1Nhici
  • 割集的边界:进程 p i p_i pi 处理的最后一个事件的集合, B = { e i c i } B = \{e_i^{c_i}\} B={eici}

一致的割集:它包含的每个事件,它也包含了所有在该事件之前发生的所有事件。如果 e i k ∈ C e_i^k \in C eikC,那么 ∀ e j k ′ → e i k ,   e j k ′ ∈ C \forall e_j^{k'} \to e_i^k,\,e_j^{k'} \in C ejkeik,ejkC

一致的全局状态:相对于一致割集的全局状态

在这里插入图片描述

快照算法

算法目标:

  • 记录进程集的进程状态通道状态
  • 算法所记录的状态组合可能并没有在同一时间发生,但所记录的全局状态是一致的

算法假设:

  • 不论是通道还是进程都不出故障
  • 通信是可靠的,每个发送的消息最终被完整地接收到恰好一次
  • 通道是单向的,提供 FIFO 顺序的消息传递
  • 描述进程和通道的图是强连通的 (在任两个进程之间有一条路径)

算法的优点:

  • 任一进程可在任一时间开始一个全局快照
  • 在照快照时,进程可以继续它们的执行,可以发送和接收正常的消息

在这里插入图片描述

Chandy-Lamport Snapshot Algorithm

  1. 标记接收规则:
    1. 进程 p i p_i pi 从接收信道 c c c 上获得标记信息(Marker Message)
    2. 如果 p i p_i pi 还没记录自己的进程状态
      1. 记录自己的进程状态
      2. 将接收信道 c c c 的状态置为空集
      3. 开始记录其他接收信道 c ′ c' c 上的消息
    3. 否则,把接收信道 c c c通道状态记录为 step 1.2.3 的所有接收到的消息集合
  2. 标记发送规则:
    1. 进程 p i p_i pi 完成了 step 1.2.1 后,
    2. 对每个发送信道 c c c 上,在发送任何其他消息之前,发送标记信息
  3. 算法启动:任一进程 p i p_i pi 从一条不存在的接收信道上接收到了一个标记

对算法的理解:

  • step 1.2,进程 p i p_i pi 启动自己的快照算法。
  • step 1.2.2,信道 c c c 上没有影响当前全局状态的消息了。
  • step 1.2.3,除了 c c c 以外的接收信道上,可能有影响当前全局状态的消息,还没接收到。
  • step 2.2,进程 p i p_i pi 的每个发送信道上,恰好发送一次标记信息。要么启动对方的快照算法,要么结束对方对这个信道的记录。
  • step 1.3,进程 p i p_i pi 的每个接收信道上,也恰好只有一次标记信息。当所有接收信道的状态都已被记录,那么终止自己的算法。

最后,这些记录下的状态,可以在各进程本地记录,也可以发送给某个指定进程来收集。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值