这不是Marzullo的算法。高阶层服务器利用多个时间源获取高精度时间,而普通客户端使用单个服务器来获取时间。
NTP时间戳以自1900年1月1日起的秒数存储。32位用于表示秒数,另外32位用于表示秒的小数部分。
同步很棘手。客户端在发送请求时记录时间戳A(所有这些值都以秒为单位)。服务器会回复包含其接收到数据包的“真实”时间(称之为X)以及将要传输数据包的“真实”时间(Y)。客户端将接收到的时间记录下来(B)。
NTP假设在网络上所花费的时间对于发送和接收来说是相同的。在充足的时间间隔内,对于正常的网络来说,平均值应该相同。我们知道从发送请求到接收响应总共需要B-A秒。我们想要去除服务器处理请求所用的时间(Y-X),只剩下网络遍历时间,所以是B-A-(Y-X)。由于我们假设网络遍历时间是对称的,因此响应从服务器传输到客户端所需的时间是[B-A-(Y-X)]/2。因此我们知道服务器在时间Y发送了其响应,而它花费了[B-A-(Y-X)]/2秒钟才能让该响应到达我们。
因此,我们接收响应的真实时间是Y+[B-A-(Y-X)]/2秒。这就是NTP的工作原理。
举个例子(为了简便计算,以完整秒表示):
在适当的实现中,客户端作为守护程序始终运行。经过长时间的多个样本测试,NTP实际上可以确定计算机时钟是慢还是快,并相应地自动调整它,即使它之后断开网络连接,它也能保持相当准确的时间。通过对来自服务器响应进行平均值处理和更复杂的思考,你可以得到非常精确的时间。
当然,一个合适的实现还有更多内容,但这就是要点。
如果您使用时间戳来确定顺序,具体时间可能并不必要。相反,您可以使用 Lamport 时钟,它比网络同步更容易处理。它可以告诉您哪个事件“先发生”,但无法告诉您确切的时间差异。它不关心计算机时钟实际上显示的时间。