您的位置:首页 > 其它

分布式系统内的时间,时钟和事件顺序

2014-11-01 11:16 417 查看
这篇博客是关于Lamport的经典论文Time, Clocks, and the Ordering of Events in the Distributed System的翻译。由于博主的水平有限,如有错误和疏漏之处,恳请读者不吝指正。

本文分析和展示了一个事件在另一个事件之前发生的概念,由此定义了事件的偏序。并给出了一个同步系统逻辑时钟的分布式算法。这个逻辑时钟可以用来获得事件的全序。这个全序的使用会作为解决同步问题的方法来讲解。这个算法然后被用来同步物理时钟,并推导出这个时钟能够达到的同步程度的界限。

关键词和短语:分布式系统,计算机网络,时钟同步,多进程系统。

介绍



时间的概念是我们思考方式的基础。它是从更基础的事件发生顺序的概念衍生而来。如果某件事件发生在我们时钟读数为3:15之前,并在读数3:16之后,我们说这件事发生在3:15。在我们关于系统的思考中充满了事件发生的时间顺序的概念。例如,在一个航空订票系统中,我们指定订票请求只有在飞机起飞之前才应该成功。然而,我们将看到当考虑分布式系统中的事件时,这个概念必须被仔细地再次检查。

分布式系统是由空间上分开,并且之间通过交换消息进行通信的不同进程的集合而组成。如ARPA等互联的计算机网络是分布式系统。一个单独的计算也可以看做是包含了中央控制单元、内存单元和输入输出通道进程的分布式系统。如果消息的传递延时相对于在单个进程中事件间隔是不可忽略的,那么这个系统就是分布式的。

我们主要是关心空间上分开的计算机系统。然而,很多我们的评论可以应用的更广泛。尤其是在单个计算机中的多进程系统,它牵扯的问题和分布式系统是类似的。因为在多进程系统中某些事件发生的顺序也是不确定的。

在分布式系统中,有时是无法说明两个事件中哪一个是先发生。”在前发生“关系因此只能是系统中事件的偏序关系。我们发现经常因为人们没能足够意识到这个事实和它的含义而发生问题。

在本文中,我们将讨论通过”在前发生“关系定义的偏序,并且给出一个算法将定义的偏序推广到所有事件的一致性全序。这个算法为实现一个分布式系统提供了一个很有用的机制。我们通过一个解决同步的简单应用来说明它的使用。意外的是,如果通过这个算法获得的顺序和用户感知的不同,那么异常行为可能发生。通过引入真实物理时钟可以避免这个问题。我们描述了一个同步这些时钟的简单方法,并且推导出这个方法能够达到同步程度的一个上界。

偏序

很多人可能会说如果事件a发生在比b更早的时间,那么事件a在b之前发生。他们可能会通过时间的物理理论来证明这个定义是合法的。然而,如果系统要正确地符合一个指标,那么这个指标必须能通过系统中可观察的事件来给出。如果这个指标是根据物理时间得到,那么这个系统必须包含真实时钟。即使它包含了真实时钟,仍然会有问题:时钟不能非常完美的准确,并不能保持精确的物理时间。因此我们将不通过使用物理时钟来定义”在前发生“关系。

首先,我们更加准确地定义我们的系统。我们假设系统是由进程集合组成。每一个进程包含一个事件序列。根据应用情况,一个计算机中的子程序执行可能是一个事件,或者一个单条机器指令的执行可能是一个事件。我们假设进程的事件形成了一个序列。如果a在b之前发生,那么在序列中a出现在b的前面。换句话说,单个进程被定义成具有一个先验全序的事件集合。将我们的定义扩展到允许进程分裂出不同的子进程的情况是非常容易的,但我们不会费心这样做。

我们假设发送和接收消息是在进程中的事件。然后,我们能够定义”在前发生“关系, 并使用"->"表示。如下:

定义:在系统中事件集合上的”->"关系是满足下列三个条件的最小关系。

(1) 如果a和b是同一个进程的事件,并且a在b之前发生,那么a->b。

(2) 如果a是一个进程的消息发送事件,并且b是同一个消息被另一个进程接收的事件。那么a->b。

(3) 如果a->b并且b->c, 那么a->c。如果两个不同的事件a和b, 且满足a-≯b和b-≯a,那么a和b被认为是并发的。

假设对于任何事件a, 都有a->/a,这就表示了"->"是系统中的所有事件集合的不自反偏序关系。

根据如图1的“时空图”来看这个定义是很有帮助的。水平方向表示空间,竖直方向表示时间 -- 更晚的时间比更早的时间高。点表示事件,竖直线表示进程,波浪线表示消息。容易看出 a->b意味着能通过在图中沿进程和消息线向前移动可以从a走到b。例如,在图1中的 p1->r4。



查看这个定义的另一种方法是, a->b 意味着事件a可能因果影响到事件b。如果两个事件没有因果影响,那么它们是并发的。例如,在图1中事件p3和q3是并发的。即使我们已经画出的图中暗示了q3在p3更早的时间发生,然而直到进程P在p4接收消息之前,它不会知道Q在q3做了什么。(在事件p4之前,P可能至多知道Q计划在q3做的事件)

这个定义对于熟悉在【1】中描述的不变的狭义相对论的时空公式的读者是非常自然的。在相对论中,事件的排序是根据可能被发送的消息来定义的。然而,我们采用更加实际的方法,就是只考虑实际被发送的消息。我们只知道那些确实发生的事件,而不知道可能发生的事件,应该能决定系统是否执行正确。

逻辑时钟

我们现在引入时钟到系统中。先从一个抽象的视角开始,时钟仅是赋予数字给一个事件的方法。这个数字被认为是事件发生的时间。更精确一点,我们将每个进程Pi的时钟Ci定义成一个函数。这个函数赋予数字Ci(a)给进程Pi的事件a。时钟的完整系统通过给任何事件b赋予数字C(b)的函数C表示。如果b是进程Pj的事件,那么C(b)=Cj(b)。到现在,我们没有做任何假设说数字Ci(a)和物理时钟相关,所以我们可以认为时钟Ci是逻辑时钟,而非物理时钟。它们可以通过计数器来实现,而不需要真实的时间机制。

我们现在考虑什么可以说明这样的时钟系统是正确的。我们不能将我们正确的定义基于物理时钟,因为这将要求引入保持物理时间的时钟。我们的定义必须基于事件发生的顺序。最强的合理条件是如果一个事件a发生在另一个事件b之前,那么a应该发生在比b更早的时间。我们如下更正式地说明这个条件。

时钟条件:对于任何事件a,b:
如果a->b,那么C(a) < C(b)

注意,我们不能期望这个条件反过来也成立,因为这将暗示任何两个并发事件必须同时发生。在图1中,p2和p3都是和q3并发,所以这将意味着他们必须都和q3发生在同一时间。这将违背时钟条件,因为p2->p3。

从关系“->"的定义可知,如果下列两个条件成立,那么时钟条件满足。
C1:如果a和b是进程Pi的事件,且a在b之前发生,那么Ci(a)<Ci(b)。
C2:如果a是进程Pi的消息发送事件,且b是同一个消息的被进程Pj接收的事件。那么Ci(a)<Cj(b)。

让我们根据时空图来思考这个时钟。我们设想一个进程的时钟”ticks"经过每一个数字,并且"ticks"发生在进程事件之间。例如,如果a和b是进程Pi的相连的事件,并有Ci(a)=4和Ci(b)=7,那么时钟ticks 5, 6和7发生在这两个事件之间。我们画一条通过不同进程的所有的like-numbered ticks的虚tick线。图1的时空图可以衍生出图2中的图片。条件C1意味着同一进程线的任何两个事件之间必然有一个tick线,并且条件C2意味着每一个消息线必然穿过一个tick线。从->的图画含义很容易看出为什么那两个条件意味着时钟条件。



我们可以认为tick线是在时空上某个笛卡尔坐标系统的时间协调线。我们可以重新画图2来将这些协调线弄直,这样我们得到图3。相对图2, 图3是一个有效表现同样事件系统的另一种方式。因为没有引入物理时钟的概念到系统中,无法决定这些图片哪个是最好的表示。



读者可能发现可视化进程的二维空间网络是很有帮助的。这将衍生出三维时空图。进程和消息依然用线来表示,但tick线变成了二维面。

让我们现在假设进程是算法,而事件是它们执行过程中表现的特定行为。我们将展示如何引入时钟到进程中,并满足时钟条件。进程Pi的时钟通过寄存器Ci来表示,所以Ci(a)是事件a发生时的Ci的值。Ci的值将在事件之间改变,所以改变Ci自身不会构成时间。

为了保证时钟系统满足时钟条件,我们将确保它满足条件C1和C2。条件C1是很简单的;进程需要循下列实现规则:
IR1: 每个进程Pi在任何两个相连事件之间增长Ci。

为了满足提条件C2,我们要求每个消息m包含一个时间戳Tm。Tm等于这个消息m的发送时间。根据这个消息的事件戳,接收这个消息的进程将它的时钟向前调整到比Tm晚的数值。更精确地,我们有下列规则。
IR2:
(a)如果事件a是进程Pi发送消息m事件,那么消息m包含时间戳Tm=Ci(a)
(b)进程Pj根据接收到的消息m, 设置Cj成大于或等于它现在的值,并保证比Tm大。

在IR2(b)中, 我们考虑表示消息m的接收事件在Cj设置后发生(这仅是概念上的麻烦事,并和具体的实现无关)。很明显,IR2能够确保C2得到满足。因此,简单实现规则IR1和IR2意味着时钟条件得到满足,所以他们保证了一个正确的逻辑时钟系统。

待续。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: