WHY
在网路世界中, 各个计算机之间要想协同工作, 时间同步是一个非常重要的基础. 在计算机内部是有自己的时间的, 这个时间通过内部的晶体振荡器差生的固定频度, 来模拟时间流逝进行估算. 虽然频度非常稳定, 但也是有偏差的, 虽然现今的工艺水平偏差早已非常小了. (关于回落的具体原理, 在此不表)
既然本地时间会形成偏差, 那么都会导致两台服务器的时间不一致. 要清除不一致, 就须要有一个统一的时间标准, 然后你们都以这个标准为基准时间并对自己的本地时间进行校正, 既协调国际时(UTC), 关于这个时间是如何来的, 不是本文讨论的重点.
好了, 现在, 在另一个地方, 有一个标准时间, 如何将这个标准时间通过网路同步到你的本地计算机呢? 如何在同步的过程中, 尽量去除网路延后带来的影响呢?
HOW
如果直接进行网路恳求, 然后领到一个返回时间戳并更改本地时间可不可以呢? 显然不行. 别忘了, 包在网路中传输也是须要时间的, 这个恳求从对方发出, 至抵达本地计算机, 经过了多久你并不知道, 这中间的延后会严重影响时间校正的结果.
OK, 现在碰到的问题就是网路延时了, 如果能否去除网路延后, 就可以精准同步了, 但以现今的技术水平是做不到的. 既然延时难以清除, 如果我们能否晓得这个延时的时间, 也可以通过估算清除延后的影响.
包在网路中的传输大致如图:
#3:0:e:6:8:6:a:a:0:5:2:d:a:3:3:f:3:9:5:f:5:f:9:8:c:5:5:1:d:1:f:8#
其中各值如下:
我们现今的目的看起来很简单, 就是在接受到返回的时侯, 将本地时间C2 校准为SC2. 首先要明晰的是, C2和SC2是不想等的, 否则两者时间相同就不需要校正了嘛.
首先, 我们本地晓得的信息有: C1, C2, 可以令服务器在返回结果中, 告诉我们S1, S2. 并且, 我们假设网路中的延时是基本固定的, 既S1-C1=C2-S2.
好了, 现在早已成功的将其转换成了一道物理题. 是不是忽然发觉简单了许多? 步骤如下:
如何? 很巧妙的将网路延时清除了.
以上, 就是时间同步ntp合同的内容了. 不过, 如此同步的时间也是有偏差的, 首先里面就假定了往返的网路延时相同, 如果延时不对称, 则同步结果都会不确切, 而且, 协议跑在应用层, 从数学层到应用层之间的串扰也会影响最终结果.
应用
我们在实际实际编程中, 经常会写入类似这样的代码:
#d:e:3:4:2:7:b:0:4:b:4:e:5:9:e:3:c:1:9:8:f:e:e:9:9:0:4:9:3:6:a:d#
如果, 在获取$t1变量后, 正巧进行了时间同步, 那么$t2有可能大于$t1, 岂不是很奇特. 不过还好, 有不同的同步方法供我们选择, 以下在Ubuntu系统上进行了测试.
不过, 在我的服务器Ubuntu 18上, 已经默认不再使用ntp工具了, 转而使用timedatectl, 其内部合同是一样的, 有关timedatectl的详尽内容可以参考一下官网的说明:
#a:3:a:a:7:e:a:7:b:f:1:2:0:b:e:f:5:9:c:1:6:a:9:5:5:e:a:e:0:d:8:2#