4. NTP同步算法与时钟纪律

NTP 的同步过程并不是简单地“把本地时间改成服务器时间”。如果直接跳变系统时钟,会破坏依赖单调时间的应用(如数据库事务、日志顺序、定时器)。NTP 真正做的是两件事:先估计本地时钟相对参考源的偏移(offset)与频率偏差(frequency skew),再通过时钟纪律(clock discipline)以平滑、可控的方式调整本地时钟。理解这条链路,才能理解 NTP 的精度边界究竟由什么决定。

偏移与频率偏差的估计

NTP 客户端与服务器之间交换四个时间戳:客户端发送时刻 T1、服务器接收时刻 T2、服务器回复时刻 T3、客户端收到回复时刻 T4。假设往返路径对称,则:

往返时延 delay = (T4 - T1) - (T3 - T2)
时钟偏移 offset = [(T2 - T1) + (T3 - T4)] / 2

这里约定:offset 为正表示本地时钟慢于服务器,需要向前拨;为负表示本地时钟快于服务器。这个约定在后续所有计算和图示中保持一致。例如一次交换中 T1=1000.000s、T2=1000.050s、T3=1000.052s、T4=1000.102s,则 delay=(0.102-0.000)-(0.052-0.050)=0.100s,offset=[(0.050)+( -0.050)]/2=0.000s,说明路径对称且本地时钟恰好对齐。若 T4=1000.112s,则 delay=0.110s,offset=[0.050+(-0.060)]/2=-0.005s,本地时钟快了 5ms。

单次测量受排队抖动影响很大,因此 NTP 会对同一服务器连续采样,用滤波(如加权中值、最小延迟优先)从多个样本中提取“最可信”的偏移估计。频率偏差则通过观察偏移随时间的变化率来估计:若连续两次测得 offset 从 +10ms 变为 +4ms,间隔 64s,则本地时钟相对参考源约快 (10-4)/64 ≈ 0.094 ms/s,即约 94 ppm,需要相应调慢频率。

Marzullo/交集算法与时钟选择

当客户端配置了多个服务器时,每个服务器给出的不是一个点估计,而是一个区间 [offset-δ, offset+δ],δ 由根距离、延迟和离散度决定。Marzullo 算法的目标是找到被最多区间共同覆盖的重叠区间,作为“真实时间”的候选范围。若某个服务器的区间与其他多数区间不重叠,它就被判定为 falseticker(错误时钟源)并被剔除。

NTP 实际使用的是 Marzullo 的改进版本,并配合时钟选择(selection)与聚类(clustering):先按层级、根距离、同步距离筛选出候选源,再用交集算法找出可信区间,最后通过聚类逐步剔除偏离较大的源,保留一组相互一致的“幸存者”,并从中选出一个系统 peer 作为主参考。这个过程决定了 NTP 对“坏钟”的容忍能力,也决定了多源配置比单源更稳健的原因。

NTP 时钟选择与交集算法示意 -30ms -10ms 0 +10ms +30ms Server A [-8ms, +4ms] Server B [-2ms, +10ms] Server C [+22ms, +34ms] 交集 [-2ms, +4ms] 与多数区间不重叠 → falseticker 被最多区间覆盖 → 可信偏移范围

锁相环与时钟调整策略

得到偏移和频率估计后,NTP 用锁相环(PLL)或频率锁定环(FLL)来驱动本地时钟。PLL 关注相位(即偏移)对齐,适合稳态下维持微小误差;FLL 关注频率对齐,适合初始捕获或偏移较大时快速收敛。NTP 通常采用混合策略:偏移大时先以频率调整为主,逐步把偏差拉回;偏移小时切换到相位微调,避免频繁跳变。

调整方式主要有两种:步进(step)和 slew(渐进调整)。步进直接设置时钟,速度快但会造成时间不连续;slew 通过临时改变时钟频率,让时间“慢慢追上”,通常限制在 500 ppm 以内,保证单调性。工程上一般只在启动阶段或偏差超过阈值(如 128ms)时允许 step,之后一律用 slew。Linux 的 ntpd 默认在偏差小于 128ms 时使用 slew,chronyd 则更激进地默认使用 slew,并可通过 makestep 指令控制何时允许跳变。

NTP 精度边界分析

NTP 的精度受多重因素制约。首先是路径不对称:offset 公式假设往返延迟对称,若上行 20ms、下行 5ms,则计算出的 offset 会引入约 7.5ms 的系统误差。其次是网络抖动与排队:交换机队列、无线重传、CPU 调度都会让单次测量离散度增大,滤波只能缓解不能消除。第三是本地时钟质量:晶振漂移、温度变化、虚拟化环境中的时钟虚拟化都会影响频率估计的稳定性。第四是服务器层级与根距离:每经过一级 NTP 服务器,误差会累积,Stratum 越高,可达精度越差。

在局域网内,NTP 通常可达到亚毫秒到几毫秒精度;广域网典型为几毫秒到几十毫秒;跨洲或高抖动链路可能达到几十到上百毫秒。若需要微秒级精度,应改用 PTP(IEEE 1588)并配合硬件时间戳。理解这些边界,才能在工程中合理设定 maxpoll、minpoll、tos 等参数,并对同步结果做出正确判断。

判断 NTP 是否健康,可观察 ntpq -p 输出中的 offset、jitter、delay 和 reach。offset 持续在 ±几毫秒内、jitter 小、reach 为 377,通常说明同步稳定;若 offset 反复大幅摆动或某个源长期被标记为 falseticker,应检查网络路径和服务器配置。