分布式事件排序
分布式系统最难的一点在于,我们常常发现需要用与计算领域其他问题截然不同的方式来处理它们。分布式计算迫使我们重新评估如何在单一系统模型中处理哪怕是最简单的问题。
最近,我们开始探索一个这样的例子,当时我们仔细研究了滴答作响的时钟,并发现它们在分布式系统中是多么不可靠!正如我们所了解到的,分布式系统中没有单一的全局时钟,这使得很难就时间达成一致。理解时钟和时间的注意事项对于理解分布式计算模型至关重要。
但时间为何如此重要?我们为何如此在意时间?了解事件发生的时间又为何如此重要?如果时间如此重要,那么在没有全球时钟的情况下,我们该如何确定时间呢?正如我们将要了解到的,我们真正关心的并非时钟和时间本身,而是与它们息息相关的事件。
人类心智中的时间
虽然我们已经对时间这个话题有了初步的了解,但还有很多东西有待我们去探索。事实上,到这篇文章结束的时候,我们甚至都还没说完时间!现在,花这么多时间去学习时间似乎有点奇怪。那么,为什么时间在分布式系统中如此重要呢?如果我们更深入地思考,我们可能会意识到,在分布式系统中,我们并不特别关心时间。我们关心的是能够依靠时间来帮助我们安排事情。

时间概念帮助我们对单个系统和分布式系统中的事件进行排序。
在系统中对事件进行排序时,时间尤为有用。大多数程序员在处理数据或流程时,都会依赖并期望某种时间格式;这种时间格式通常类似于时间戳,它是一串经过编码的字符,用于表示某个特定时刻。我们使用时间戳来记录某些数据的创建或更新时间、消息的发送或接收时间,以及进程的启动或完成时间。实际上,我们并不关心时间戳本身——真正有用的是与某些数据或事件相关联的时间戳。
然而问题在于,我们人类有自己的时间观念以及时间应该如何运作。

我们倾向于认为时间是线性的;一个事件发生在“某个”时间,另一个事件在它之后的“另一个”时间发生,最后一个事件最后发生在某个“最终”时间。

人类的时间心理模型假设了一些事情。
- 首先,我们都认同现在的时间。我们拥有不同的时区和共用的时钟(包括全球原子钟),因此在特定地点的时间方面,我们之间几乎没有任何差异。
- 其次,我们倾向于认为事件是接连发生的。事件A先发生,然后是事件B,最后是事件C。
- 第三,我们可以根据事件发生的先后顺序来确定事件发生的确切顺序。换句话说,如果事件 A 发生在事件 B 之前,并且我们知道 A 和 B 发生的时间,我们就能知道这两个事件发生的确切顺序。
虽然这对我们来说似乎显而易见,但这种时间的思维模型在分布式系统的背景下却行不通!我们人类对时间运作方式的思维模型与分布式系统中的现实时间之间存在一些重大差异。

第一个区别是我们已经知道的:分布式系统没有全局时钟,因此无法确定不同位置的不同机器上的时间。需要注意的第二个区别是事件不是一个接一个发生的!事件可以同时发生,并行发生,或并发发生。这两点都引出了另一个主要区别:事件发生在不同的地方,系统中的不同节点/位置。但是,因为它们可以同时发生,并且因为没有全局时钟就不可能知道时间,所以在整个分布式网络中发生的事件很难排序!
人类对时间的建模和分布式系统中时间的现实,是我们在系统中对事件进行排序时所采用的两种截然不同的方法。在人类模型方法中,我们知道确切的时间,因此很容易确定如何对某些事件进行排序——我们可以直接使用每个事件的时间戳,因为我们知道具体时间!但在分布式系统方法中,我们无法掌握系统中所有事件的全部信息(也就是知道时间)。
全序和部分序
人类对时间的建模,以及分布式系统中更现实的时间观,可以归结为两种截然不同的事件排序方法。让我们进一步了解一下。

我们对时间的理解与单一系统的时间模型高度一致。在单一系统中(而非分布式系统),每个事件都可以根据其发生时间按特定顺序排列。这也称为事件的全序。
当系统中的事件遵循全序时,系统中的每个事件都有其特定的发生顺序。换句话说,当我们确切地知道每个事件发生的时间时,我们就知道了系统中所有事件的全序。
例如,在上图中,如果我们知道事件 A 首先发生,然后是事件 B,最后是事件 C,那么我们就能知道所有事件的全序。单个系统中的事件可以是全序的,因为我们有一个本地时钟来帮助我们确定事件发生的确切时间,这使我们能够确定所有事件的全序。
然而,分布式系统与单一系统截然不同!当然,系统中的单个节点会根据其本地时钟知道当前时间,但它无法知道其他节点上的时间。这几乎就像分布式系统中的每个节点都能够达到全排序的一半……它可以对自己的事件进行排序,但如果它收到来自系统中其他节点的任何消息/传入事件,它将不知道该如何处理它们。

这就引出了偏序,它是全序的“不太确定”版本。在偏序中,我们无法确定系统中所有事件的确切顺序。相反,我们唯一能确定的是相互依赖的事件的顺序。
让我们回想一下我们之前的例子,三个事件:A、B 和 C。在单机系统或全序系统中,我们能够知道每个事件的确切顺序。但在分布式系统中,情况可能并非如此!相反,我们可能对某些事件有把握,但对其他事件则不然。

例如,假设我们确定事件 B 和事件 C 发生的时间。事实上,我们甚至确定事件 B 发生在事件 C 之前。但是事件 A 呢?我们根本不确定它发生的时间!
实际上,由于我们不知道事件 A 何时发生,理论上它可能在任何时间发生:事件 B 之前、事件 C 之后,甚至在两事件之间!我们唯一可以肯定的是,事件 B 发生在事件 C 之前。
事实上,我们对如何对这些事件进行排序的部分确定性使得这组事件成为部分排序——我们只是“部分”确定这些事件的顺序。

在分布式系统中,我们主要处理部分有序事件,这是因为各个节点可以确定如何对本地事件进行排序,但它们无法始终确定如何对其他节点上发生的事件进行排序。分布式系统中的节点会向其他节点发送消息,而这些节点并不一定确定这些消息的发生时间。同样,系统中的一个节点会接收它自己的一组传入消息,并且它也无法确定这些消息的发送时间!
那么,我们该如何协调整个系统对时间的认知缺失呢?嗯,这需要我们重新思考时间的概念……以及我们到底是否需要时间(?!)。
也许时间并不重要
在这篇文章的开头,我们问过自己,我们为什么要关心时间。我们意识到,这个问题不断出现,是因为我们依赖时间来对系统中的事件进行排序。在此过程中,我们了解到,有时我们可以确定事件的顺序(全序),而有时,我们无法确定所有事情(偏序)。但如果我们回到最初的问题,我们可能会意识到,我们实际上并不关心时间,而是关心事情发生的顺序。

或许我们实际上并不需要担心系统中每个事件发生的确切时间。相反,我们应该尝试用一种甚至不需要思考时钟或时间的方式来确定这些事件发生的时间!
我们真正想知道的是某些事件发生的顺序。为什么我们要关心事件的顺序呢?嗯,对事件进行排序的主要好处在于,我们可以弄清楚一个事件是如何引发另一个事件发生的。那么,问题来了:如何才能既享受事件排序带来的好处,又不用费力去确定每个事件发生的时间呢?

这个谜题的答案是因果排序,它帮助我们根据因果关系而非发生时间对事件进行排序。因果排序重塑了我们对事件的思考方式。如果我们能弄清楚哪些事件导致了其他事件,就能对这些事件的发生做出一个大致的排序。
换句话说:我们再也不需要关心时间了!我们可以绕开它,直接切入核心问题:弄清楚一个事件是否发生在另一个事件之前。在下一篇文章中,我们将深入探讨因果顺序背后的逻辑,并找出事件之间的时间关系。与此同时,请放心,我们已经找到了一个(合乎逻辑的)时间解决方案。
资源
在学习更复杂的时间相关主题之前,了解分布式系统中事件的顺序非常有帮助。在分布式系统中,很难找到专门解释全序和偏序的资源,但有一些资源做得相当不错,我在下面列出了它们!
- 分布式系统的乐趣和利润,Mikito Takada
- 分布式系统中事件的部分排序,Jesse Bangs
- 分布式系统:有序性和一致性,AF Cooper 教授
- 因果排序,杰米·布兰登
- 分布式系统中的时间、时钟和事件排序,Leslie Lamport
鏂囩珷鏉ユ簮锛�https://dev.to/vaidehijoshi/ordering-distributed-events-2o7b