在开发分布式系统时,比如利用Scrapy-Redis实现分布式爬虫,其核心原理就是使用一个中心节点来分配爬虫任务,这种常见的形式,其实是伪分布式,因为核心还是要依赖中心服务器,那真分布式系统要怎么实现呢?本文从分布式系统中时钟的角度来讨论目前分布式系统的原理。
计算机中的硬件时钟
如果我们的计算机好几天没有连接互联网,当你再次打开计算机时,操作系统中显示的时间依旧是正确的时间,要做到这点,就需要使用计算机主板上一个称为「石英晶体振荡器」(简称晶振)和一个纽扣电池,如下图:
计算机主板上的晶振的频率是32768Hz每秒,在通过纽扣电池通电时,石英晶体每振动32768次,电路就出传出信息,表示1秒,计算机在断网情况下,可以通过这种方式来记录时间(跟石英表一样的原理),但这种方式统计的时间是有误差的,正常情况下,每天的计时误差在正负1秒左右,但日积月累,就会出现时间漂移,让时间误差大到无法接受的程度。
NTP协议
因为石英晶体误差较大,所以在1985年,David L. Mills设计了网络时间协议NTP(Network Time Protocol)来同步不同计算机之间的时钟,NTP协议的目的是将所有计算机之间的时间误差缩小到几毫秒内。
目前我们的计算机就在使用NTP协议,在广域网中,因为网络传输需要时间,所以误差会到几十毫秒内,而在局域网中,网络传输延迟低,局域网中计算机之间的时间误差可以降低到1毫秒内。
NTP协议采用主从式架构,如下图所示:
NTP协议架构
第0层,基准时钟
使用高精度计时设备实现时间的记录,如铯或铷原子钟、GPS时钟等,它们生成的脉冲信号非常准确。
第1层,主时间服务器
主时间服务器与第0层设备相连接,在几微秒误差内同步系统时钟,此外除第0层外,其他层之间的服务器都可以相互连接。
第2、3层,与第1层类似,不再赘述,关于NTP协议的更详细的信息,可以看NTP 协议简单分析一文。
NTP协议的误差不影响人类对时间的感知,但在分布式系统中,已经会出现问题,比如一个计算机发送了A信号,再发送B信号,即逻辑上A信号是早于B信号的,但因为网络原因,可能B信号先到达,先被处理,这就很不合理。
Lamport逻辑时钟
因为NTP协议存在误差,所以无法在分布式系统中确定两个事件发生的先后顺序,那怎么才能确认事件的先后顺序呢?
在思考怎么能之前,思考一下,为什么我们需要在分布式系统中对事件进行排序?
假设,在分布式数据库中,有多个并发执行的事务,此时需要做事务隔离,以我们熟悉的MVCC(Multiple Version Concurrent Control)多版本并发控制为例,MVCC会根据数据的版本号来控制该版本数据的可见性,这就需要知道数据修改事件发生的先后顺序才能实现正确的隔离。
那怎么才能实现分布式系统中的事件排序呢?
Lamport逻辑时钟便是这个问题的经典解决方法,该方法由图灵奖得主Leslie Lamport在他1978年的论文「Time, Clocks, and the Ordering of Events in a Distributed System」提出的。
偏序与全序的概念
理解Lamport逻辑时钟前,需要理解偏序(partial order)和全序(total order)这两个概念。
偏序的定义如下:
假设是集合S上的一个二元关系,如果满足:
1.自反性:对S中任意的元素a,都有
2.反对称性:如果对于S中的两个元素a和b,,那么
3.传递性:如果对于S中的三个元素,有,那么
全序相比于偏序,多了一个完全性:
1.完全性:对于S中的任意a和b元素,必然有或
简单而言,偏序就是集合中的元素是部分有序的,而全序就是集合中任意一对元素都是有序的,从下图直观理解偏序与全序。
S1描述了全序关系,S2描述了偏序关系
集合描述的是正整数之间的大小顺序,集合中任意一对元素都是有序的,所以集合是全序的