顺序的分类
在分布式系统中, 顺序关系主要分为以下三类:时间顺序: 事件在时间轴上发生的先后关系。
无限时刻集组成有向时间轴, 时间顺序是通过时刻的顺序体现的。
因果顺序: 如果事件e1是事件e2发生的原因, 那么e1的微小变化( 一个标记) 就会引起e2的微小变化, 但e2的微小变化不一定与e1的微小变化有关, 则称e1和e2存在因果顺序。
传递顺序: 由协议约定的一种弱顺序关系。
传递顺序不一定与时间发生的时序有关, 也不一定与事件之间的因果顺序关系有关。 如分布式系统的原子广播算法。
时钟
物理时钟与参考时钟
时钟漂移
时钟的失效模式
物理时钟有两种失效模式, 如下图:( 1) 故障使计数器值出现错误。( 2) 时钟计时开始加快或变慢, 导致时钟漂移率偏离指定的漂移率范围( 偏离图中的阴影部分) 。
时钟精密度与时钟准确度
时钟精密度与时钟准确度
时间标准
国际原子时( International Atomic Time, TAI)
国际原子时( International Atomic Time, TAI) : 1秒定义为铯原子进行9192631770次能级跃迁所用的时间。
实验室时间, 不受地球旋转和振动的影响, 及其稳定, 没有闰秒;
由位于巴黎的国际时间局( BIH) 维护, 取世界上数十个铯原子钟的平均值( 滴答次数) 产生;
TAI的起始时间是格林威治时间1958, 1, 1的00:00;
GPS系统采用TAI时间标准, 每个GPS卫星上有4个原子钟。 通常地面GPS终端的授时单位为1pps( 每秒一个脉冲) , 精度在10ns级别。
协调世界时( Universal Time Coordinated, UTC)
协调世界时( Universal Time Coordinated, UTC) : 天文观测时间, 与地球太阳之间的运动保持一致。
86400个TAI秒( 24h) 现在比一个天文观测日少3ms。 BIH通过闰秒解决该问题, 即当TAI计时和天文观测计时之间的差增加到800ms时使用一次闰秒;
UTC时间和TAI时间在1958, 1, 1的00:00是一致的, 之后到目前已经偏离了TAI时间大约30s。 向UTC插入闰秒的时间点由BIH公布;
UTC是现在“ 挂钟” 的时间基准。
时间测量
全局时间
例子
下图给出两对事件, 一对事件是17和42, 另一对事件是72和97, 它们的真实时间间隔同为25个微节拍, 观测节点赋予事件的全局节拍用小圆圈标出。 可以看出, 用时钟j, k分别观测起始事件17和结束事件42, 得到的时间间隔为1个宏节拍; 而用时钟k, j观测起始事件72和结束事件97, 得到的时间间隔为4个宏节拍。
π/Δ-领先
下表给出了不同 0/Δ-领先情况下, 事件时间戳之间的最小差别
根据时间戳建立事件的时序, 至少需要两个节拍的差别, 因此,0/3g-领先的事件集能够依据时间戳建立时序。
时间测量的基本限制
拥有粒度为g的合理全局时基的分布式实时系统, 其时间测量受到以下限制:
( 1) 两个不同结点( 时钟) 观测同一事件, 时间戳可能相差一个节拍。 两个事件的时间戳相差一个节拍, 根据事件的时间戳重建时序是不够的。
( 2) 观测到的时间间隔为d_obs, 则真实的时间间隔 d_true 受到
的限制。
( 3) 两个不同结点观测两个事件的时间戳差别大于或等于2个节拍的事件, 可以根据时间戳恢复其时序。
( 4) 事件集至少0/3g-领先, 才能根据事件时间戳恢复它们的时序。 ( 两个不同结点观测两个事件的时间戳才一定≧ 2个节拍)
内部时钟同步
内部时钟同步的目的是保证正常节点的全局时间节拍在指定的精密度Π内产生。
同步条件
中央主节点同步算法
中央主节点同步算法是非容错同步算法, 被很多协议采用。
中央主节点是独一无二的节点, 它周期性地向从节点发送带有其时间计数器值的同步报文, 为从节点提供精确
的当前时间。
从节点一旦从主节点收到同步报文, 立刻记录本地时间计数器的值, 然后计算时间值与同步报文中包含的主节
点时间计数器值的差值, 从所得差值中再去除报文传输时间, 即可获得主节点与从节点的时钟偏差。
从节点根据这个偏差修正其时钟, 使主/从节点的时钟保持一致。
由于主节点的同步报文传输到各个从节点的时间存在差异,因此中央主节点同步算法的收敛函数Ф取决于主节点读取时钟值事件与同步报文到达所有从节点事件之间的执行时间抖动ε。
缺点:
一旦主节点失效, 重同步就终止了, 从节点的时钟很快就会偏离精密度范围。
解决策略:
为中央主节点设立备份的“ 影子” 节点, 一旦主节点失效, “ 影子” 节点将承担起主节点的同步作用。
延迟抖动的补偿
在分布式系统的同步过程中, 同步报文传输的时间延迟抖动是影响同步精密度的最重要因素。 为了获取更高的同步精密度,需要对报文传输的延迟时间抖动进行补偿。
延迟时间抖动的大小主要取决于同步报文被封装和释义的系统层次。 如下表所示:
延迟抖动的补偿算法中,Cristian提出的方法应用最多。
分布式容错同步算法
分布式容错同步算法针对的是系统中不存在中央主节点时的内部时钟同步问题。 当系统存在故障节点而对其他节点的同步产生影响时, 具有一定的容错性。
分布式容错时钟重同步通常分为三个阶段:
第一阶段, 每个节点通过报文交换获得其他节点的全局时间计数器值;
第二阶段, 各个节点分析收集到的信息, 检查是否有错误, 然后执行收敛函数, 得出本地全局时间计数器的修正值。 若某个节点利用收敛函数计算出来的修正值大于集合的规定精密度, 则节点自动停用;
第三阶段, 节点根据修正值调整本地时间计数器。
分布式容错同步算法可以在一定程度上克服因出现拜占庭错误的节点, 而对其他节点的同步产生影响。
容错平均( Fault Tolerant Average, FAT) 算法
分布式容错平均( Fault Tolerant Average, FAT) 算法在N个节点组成的系统中, 若要容忍x个拜占庭故障, 算法的实现过程如下:
( 1) 每个节点收集本地时钟与其他节点的时钟之间的时间偏差, 得到N-1个时间偏差, 加上自身的时间偏差( 0) , 总计得到N个时间偏差;
( 2) 将这些时间偏差由大到小排序, 去除序列中的x个最大和最小偏差( 假定错误的时间值大于或小于余下的时间值) ;
( 3) 根据定义, 剩余序列中的N-2x个时间偏差位于精密度窗口内( 因为只有x个值被假定是错误的, 并且错误的值大于或小于正确值) , 它们的平均值就是节点时钟的修正项。
例子
例: 某集合由9个节点组成, 要求容忍2个拜占庭故障, 其中1个节点与其他8个节点的时间偏差为: -3、 15、 11、 9、 8、 13、 -5和6, 该节点时钟的修正项为多少?
解: 加上该节点自身的时间偏差0, 所有时间偏差由大到小排序后的偏差序列为:
zlist = {15, 13, 11, 9, 8, 6, 0, -3, -5}
已知x=2, 去除2个最大和最小偏差后的偏差序列为:
zlist’ = {11, 9, 8, 6, 0}
则节点时钟的修正项( 省去小数位为) :
zCorrectValue=(11+9+8+6+0)/5=6
容错中值( Fault TolerantMidpoint, FTM) 算法
另一种分布式容错同步算法是容错中值( Fault TolerantMidpoint, FTM) 算法。 算法的实现过程如下:
1) 不使用节点自身的时间偏差, 从偏差序列中去除的最大和最小值个数 y 是一个系统参数, 要根据偏差值的个数来确定,而不是拜占庭故障数。
2) 修正值的计算方法为: 首先去除时间偏差序列中的 y 个最大值和 y 个最小值, 然后取出剩余时间偏差序列中的最大值和最小值, 将其平均值作为修正值。
FTM算法有利于简化硬件设计和克服某些不稳定故障的影响, FlexRay总线中采用了这种算法。
上表中, zCorrectValue为修正值, zlist(m)为时间偏差由大到小排序后的序列中的第m个修正值。
例子
根据FTM算法, 前文的例子中, zlist = {15, 13, 11, 9, 8, 6,-3, -5}, length=8, 查表可知 y=2, 则:zCorrectValue = (zlist(3)+zlist(8-2)) = (11+6)/2 =8
时钟同步
内部时钟同步---状态修正与速率修正
收敛函数计算出来的修正项目可以立即应用于本地时间值的修正( 简称状态修正) , 也可以应用于时钟速率的修正( 简称速率修正) 。
状态修正会在时基中产生不连续性。
为保证时钟在下一个重同步间隔( Rint) 中能获得更好的连续性, 需要对时钟的速率加速或减速, 从而使它与时钟集合中的其余时钟更好地保持一致。
在数字域中, 通过改变某些宏节拍中的微节拍数可以实现速率调整; 在模拟域中, 通过调整晶振电压可以实现速率修正。
外部时钟同步---运行原理
外部时钟同步是将簇内的全局时间与外部标准时间相联系。
外部标准时间以一个时间服务器的形式周期性地播报含有当前基准( reference) 时间的时间报文 。
时间报文在簇内指定节点上引发一个同步事件, 并依据约定的时间标度( time scale) 标识此同步事件。
时间服务器的接口节点称为时间网关。
时间服务器针对簇内节点的同步过程类似于一个中央主节点的对其他节点的同步过程, 必要时也要通过延迟补偿算法来消减同步报文传输的时间延迟抖动。
GPS信号带有TAI标准时间, 精度达到10ns~100ns, 可以作为一种外部标准时间。
如果另外一个簇通过二级时间网关连接到“ 原始簇” , 次级时间网关可把原始簇的同步时间作为自己的基准时间, 并同步次级簇的全局时间。
外部时钟同步---时间格式
NTP( Network Time Protocal) 时间格式: NTP时间格式是因特网中推荐的时间格式, 如下图所示, 其中第二字段表示秒的分数, 分辨率为。
NTP时间基于UTC, 因此是不连续的, 会产生闰秒, 有可能干扰实时系统的运行。 NTP时间的起源是1900年1月1日00:00,可以循环136年, 到2036年将重新清零。
IEEE 1588时间格式: 基于TAI秒; 秒数为6字节, 秒分数为4字节; 秒分数的时间单位为ns。 时间起源为1970年1月1日00:00
逻辑时钟---Lamport时间戳
逻辑时钟是用于标注系统中事件一致顺序的时钟, 它不需要与真实时间相同或接近, 但需要达到内部时间的一致性。Lamport算法是一个典型的同步逻辑时钟的算法。
先发生( happens-before) 关系:
表达式 a→b 读作“ a在b之前发生” , 意思是所有进程一致认为事件a先发生, 然后事件b才发生。 包括以下两种情况:
( 1) 如果a和b是同一个进程中的两个事件, 且a在b之前发生, 则 a→b 为真。
( 2) 如果a是一个进程发送消息的事件, 而b为另一个进程接收这个消息的事件, 则 a→b 也为真。
先发生关系是一种传递关系, 即: 若 a→b 且 b→c , 则 a→c。
如果事件x和y发生在两个互不交换消息的进程中( 也不通过第三方间接交换消息) , 那么 x→y 不真, y→x 也同样不真。 这两个事件称为并发的( concurrent) 。
Lamport时间戳:
如果对于事件a、 b, 能为它分配一个所有进程都认可的时间值C(a)、 C(b), 具有如下性质:
如果 a→b, 那么 C(a) < C(b)
则称C(a)、 C(b)为 事件a、 b的Lamport时间戳。
Lamport时间戳必须总是前进(增加) 的, 不能倒退(减少) 。 校正时间的操作是给时间加上一个正值, 而不能减掉一个正值。
Lamport算法例子:
下图中所示的三个进程运行在不同的机器上, 每台机器有自己的时钟, 它们以各自不同的速率工作。 当进程0的时钟滴答了6次时, 进程1的时钟滴答了8次, 进程2的时钟滴答了10次。
Lamport算法
分布式系统中所有事件分配的逻辑时间, 遵循下面的规则:
( 1) 若在同一进程中a在b之前发生, 则C(a) < C(b)。
( 2) 若a和b分别代表发送一个消息和接收该消息的事件, 则C(a) < C(b)。
( 3) 对于所有不同的事件a和b, C(a) ≠ C(b)。
Lamport算法提供了一种对系统中所有事件进行完全排序的方法。
逻辑时钟---全序多播
上述例子的问题是由于两地操作未遵循相同的操作顺序造成。
尽管操作顺序会导致利息的不同, 但是更重要的是保持两个拷贝的一致性。
需要一次全序多播( totally-ordered multicast) , 即一次将所有的消息以同样顺序传送给每个接收者的多播操作。
考虑一组彼此互相多播消息的进程。 每个消息都以它的发送者的当前逻辑时间作为时间戳。 当一个消息被多播时, 时间戳也被所有进程( 包括发送者自己) 接收。 假定来自同一个发送者的消息以它们被发送的顺序被接收,并且没有消息丢失。
进程接收到一个消息后, 放进一个本地队列中, 并根据它的时间戳进行排序。 然后接收者向其它所有进程广播一个确认消息。 按照Lamport算法来校正本地时钟, 则接收到的消息时间戳总是早于确认消息时间戳。
每个消息( 包括确认消息) 都被广播, 并认为被所有的进程接收。
Lamport时钟确保没有两个消息具有相同的时间戳, 并且时间戳反映了事件全局一致顺序。
所有进程最终将具有相同的本地队列拷贝, 所有消息都以相同的顺序交付处理。 因此, 系统建立了全序多播。
u、 v、 w三个节点对于u1、 u2、 v1、 v2的判断顺序都是根据它们的Lamport时间戳, 皆为6、 8、 18、 22建立了全序多播, 并且它们的时钟逐渐趋于接近。
Lamport时间戳: 如果 a→b, 那么 C(a) < C(b)
但是上述命题的逆命题确不一定成立, 即如果C(a) < C(b), 不一定能说明事件a就是在事件b之前发生。