技术博客

时钟同步与交易时间戳:NTP、PTP 与合规时间线

第 94 / 141 篇 · 2025-09-26 · secfin · 基础设施时钟同步合规

排查一笔"客户声称先挂单却被后到的抢走"的投诉时,第一依赖的就是时间戳;而时间戳可不可信,取决于机房里的时钟同步。这篇把时钟这条看不见的底座讲清楚。

精度要求从哪来

交易相关的时间戳有几档用途,精度要求逐级抬高:

  • 秒级:日志排障、批量作业的时间标记,NTP 默认水平就够;
  • 毫秒级:委托申报时间戳、网关接收时间。异常交易监控(《异常交易监控》篇的拉抬打压、连续申报认定)按毫秒级时间窗判断谁先谁后,时钟偏差大了,规则会把正常单误判成异常、把异常单放过去;
  • 微秒级:极速柜台的内部分析——《低延迟手段》篇那个世界的自计时需求,普通集中交易用不到。

NTP:分层与误差来源

NTP 的基本原理是客户端发一个报文四个打点时间 $t_1$(客户发送)、$t_2$(服务器接收)、$t_3$(服务器发送)、$t_4$(客户接收),用两组往返估算时钟偏移和网络延迟:

$$ \theta = \frac{(t_2 - t_1) + (t_3 - t_4)}{2}, \qquad \delta = (t_4 - t_1) - (t_3 - t_2) $$

$\theta$ 是客户端要校正的偏移量,$\delta$ 是往返延迟。公式假设去程和回程对称——一旦网络路径不对称(比如去程走光纤、回程拥塞排队),误差就进来了。这是 NTP 误差的头号来源。局域网内 NTP 能到 1ms 内,公网跨运营商常见 10~100ms,而且抖动大。

现在的实现普遍用 chrony 而不是老 ntpd:chrony 持续采样估算本地时钟的漂移率,靠调频(让时钟走快走慢)追赶,而不是ntp式的跳变修正。对服务进程来说,"走得偏快 5ms"比"突然跳回 5ms"友好得多——后者会把时间敏感的逻辑炸出一堆怪 bug。

层级结构叫 Stratum:Stratum 0 是原子钟/GPS,Stratum 1 是直接连原子钟的授时服务器,往下逐级同步。券商机房的做法是从 GPS/北斗天线建自己的 Stratum 1 时钟源,内部设备全部对着它,不依赖公网。

PTP:把打点时间挪进硬件

NTP 的打点在操作系统协议栈里完成,排队、软中断都会引入不可控抖动。PTP(IEEE 1588)的诀窍是硬件时间戳:网卡在 MAC 层收发帧的那一刻打点,内核还没见到包,时间已经记下了。配合网络设备做边界时钟(BC)或透明时钟(TC)——交换机在转发过程中把驻留时间补偿进去——全网同步可以到微秒甚至亚微秒级。

代价是全链路都要支持:交换机得换支持 PTP 的型号,网卡要支持硬件打点的型号,布线长度差都要算进去。所以现实分工是:极速柜台/高频机房上 PTP,普通集中交易和清算批量 NTP 足够。给批量作业配 PTP 是纯粹的钱没地方花。

应用层的两条铁律:墙钟对外,单调时钟对内

操作系统给两种时钟。墙钟(CLOCK_REALTIME)是日历时间,会被 NTP 校正——包括往回跳。单调时钟(CLOCK_MONOTONIC)只保证单调递增,从系统启动开始计秒,重启归零,但永不回拨。

两条铁律:

  • 对内测量一律单调时钟:超时判断、耗时统计、撮合内部的事件排序。经典事故是超时逻辑用了墙钟,NTP 校时那一刻全站在途请求集体超时。
  • 对外记录一律墙钟:回报时间戳、审计日志、报文里的时间字段。这些要的是"和全世界对得上",回拨风险靠应用层兜底。

兜底的做法是进程内缓存上次取到的墙钟值,发现新取的比缓存小(回拨了),就用缓存值加一个进程内自增的序号:

$$ T = \max(T_{\text{wall}},\, T_{\text{last}}) + \epsilon_{\text{seq}} $$

保证进程内产生的时间戳严格递增。跨进程的全局顺序不靠时间戳,靠单调递增的序列号——时间戳是给人和审计看的,序列号才是给系统排序用的(《撮合算法》篇时间优先比较的就是队列序号)。

合规视角:时间线是证据链

时间戳在监管语境里是证据。发生申报先后纠纷时,举证链是:交易所回报时间戳、本方网关接收时间戳、再到 NTP/PTP 同步日志——同步日志要留痕"谁在什么时间校了多少",证明本方时间戳和交易所的可比对。配套动作:关键节点之间时钟偏差监控(比如偏差超 50ms 告警),同步日志纳入审计保存范围(《审计日志》篇的 WORM 体系)。时钟漂移不是运维小事,是合规基础设施。

时间从哪里来:PTP 微秒到应用,NTP 毫秒保底 GPS / 北斗 卫星授时 PTP 主时钟 硬件时间戳(网卡打点) 机房交换机 BC / 透明时钟 服务器 PTP / NTP 墙钟 CLOCK_REALTIME 对外:回报时间戳 / 审计日志 会被 NTP 校正(可能回拨) 单调时钟 CLOCK_MONOTONIC 对内:耗时测量 / 超时 / 内部排序 永不回拨,重启归零 防回拨:时间戳 = 物理时间 + 逻辑序列 进程缓存上次取值,发现回拨就用缓存值 + 自增序号,保证进程内严格递增 合规要求:申报时间戳、同步日志、漂移记录三方留痕,纠纷时构成可比对证据链 监控红线:关键节点时钟偏差超 50ms 告警——异常交易认定的毫秒时间窗依赖它

时钟问题在系统里出现的形态永远是别的问题:超时雪崩、日志对不上、时序误判。把底座打对了,这些"灵异现象"会成片消失。