服务器时间对齐

举报
yd_244592142 发表于 2026/11/01 13:33:23 2026/11/01
【摘要】 1. 服务器时间不准,到底会出什么事?很多人觉得"差几秒而已,能怎样"。下面这些都是真实事故: 1.1 证书校验失败,全站 HTTPS 不可用TLS 证书有 notBefore 和 notAfter。如果服务器时钟比真实时间快了 10 分钟,而证书刚好在这 10 分钟内过期——所有 HTTPS 请求开始报 cert has expired,全站挂掉。真实案例:2017 年 GitLab 一...

1. 服务器时间不准,到底会出什么事?

很多人觉得"差几秒而已,能怎样"。下面这些都是真实事故:

1.1 证书校验失败,全站 HTTPS 不可用

TLS 证书有 notBefore 和 notAfter。如果服务器时钟比真实时间快了 10 分钟,而证书刚好在这 10 分钟内过期——所有 HTTPS 请求开始报 cert has expired,全站挂掉。

真实案例:2017 年 GitLab 一次故障,根因之一就是某台机器时钟偏差导致证书校验异常。

1.2 数据库主从复制断裂

MySQL 主从复制依赖 binlog 中的时间戳判断事件顺序。如果从库时钟比主库慢,可能出现"从库认为这条日志来自未来"的情况,轻则复制延迟飙升,重则复制中断。

PostgreSQL 的逻辑复制更严格——如果备库时钟回跳,可能导致 WAL 顺序混乱。

1.3 分布式锁失效

Redis 分布式锁靠 TTL 过期。如果持锁机器的时钟突然快进 30 秒,锁提前过期,另一台机器拿到锁——两台机器同时操作同一个资源,数据损坏。

1.4 日志排序错乱,排障困难

8 台机器的日志汇总到 ELK,按 @timestamp 排序。如果其中 2 台时钟差了 5 秒,事件顺序就是乱的——你看到"先返回响应,后收到请求",排查陷入混乱。

1.5 定时任务重复执行或漏执行

cron 任务分散在多台机器上。时钟不准则可能导致:

  • 重复执行:两台机器的时钟不同步,都认为"现在到了整点",各跑了一次。
  • 漏执行:一台机器时钟慢了,跳过了某个时刻。

1.6 一句话总结影响

偏差量 可能的后果
< 1ms 几乎无感知,高频交易除外
1ms ~ 50ms 分布式锁、数据库复制可能出现边界问题
50ms ~ 1s 日志乱序、监控指标时间偏移、告警误判
1s ~ 30s 证书校验失败、定时任务紊乱、缓存过期异常
> 30s Kerberos 认证失败、TLS 握手失败、主从复制断裂

2. 服务器时钟为什么会不准?

理解原因,才能对症下药。

2.1 硬件层面:晶振不准

每台服务器主板上有一个实时时钟(RTC),靠石英晶振驱动。石英晶振的频率受以下因素影响:

  • 制造公差:不同晶振的标称频率有 ±10~50 ppm 的偏差(1 ppm = 百万分之一)。50 ppm 意味着每天差 4.3 秒。
  • 温度漂移:温度变化 10°C,频率可能偏移 10~50 ppm。机房空调波动、CPU 负载导致的局部温升都会影响。
  • 老化:晶振使用越久,频率越漂,每年可能额外偏移 1~5 ppm。
一台典型的服务器:
  晶振精度: ±20 ppm
  → 每天偏差: 20 × 86400 / 1e6 = 1.7 秒
  → 每月偏差: ~53 秒
  → 不校时的话,一个月后和标准时间差将近一分钟

2.2 软件层面:系统时钟与硬件时钟

Linux 有两个时钟:

时钟 来源 特性 用途
CLOCK_REALTIME(墙上时钟) 内核维护,可被 NTP 调整 可能跳变 记录时间戳、日志
CLOCK_MONOTONIC(单调时钟) 内核维护,从不回退 只增不减 测量时间间隔

NTP 校时会修改 CLOCK_REALTIME。如果 NTP 一次性把时钟拨快/拨慢 10 秒,所有用 CLOCK_REALTIME 算时间差的代码都会出问题。这就是为什么测量间隔必须用 CLOCK_MONOTONIC。

2.3 虚拟化层面:时钟漂移更严重

虚拟机的时钟由宿主机的虚拟时钟驱动,额外引入:

  • VM exit/entry 延迟:每次 CPU 在 VM 和 hypervisor 之间切换,时钟都可能丢几个 tick。
  • vCPU 迁移:vCPU 在不同物理 CPU 核之间迁移,各核的 TSC(Time Stamp Counter)可能不完全同步。
  • 宿主机负载高:宿主机 CPU 满载时,VM 感觉到的"时间流速"变慢。

经验值:物理服务器不校时,一天漂 1~2 秒;虚拟机不校时,一天可以漂 10~30 秒。


3. NTP:最常用的服务器时间同步方案

3.1 NTP 的工作原理

NTP 是客户端-服务器协议,走 UDP 123 端口。一次同步交互包含 4 个时间戳:

客户端发送请求:  T1 (客户端发送时刻)
服务器收到请求:  T2 (服务器收到时刻)
服务器发送回复:  T3 (服务器发送时刻)
客户端收到回复:  T4 (客户端收到时刻)

网络单向延迟 (offset 估算):
  往返延迟 RTT = (T4 - T1) - (T3 - T2)
  时钟偏移   offset = ((T2 - T1) + (T3 - T4)) / 2

客户端调整:  本地时钟 += offset

关键假设:去程和回程的网络延迟相等。如果去程 10ms、回程 50ms,估算的 offset 会有 20ms 误差。这就是为什么 NTP 精度受网络对称性限制。

3.2 NTP 的层级结构(Stratum)

Stratum 0:  原子钟 / GPS 授时接收器(硬件参考源)
    │
Stratum 1:  直接连接 Stratum 0 的服务器(一级时间服务器)
    │
Stratum 2:  从 Stratum 1 同步的服务器
    │
Stratum 3:  从 Stratum 2 同步的服务器(你的业务服务器通常在这层)

每多一层,精度大约降一个数量级。Stratum 3 的典型精度是 1~50ms。

3.3 chrony vs ntpd:该用哪个?

ntpd 是传统 NTP 守护进程,chrony(chronyd)是现代替代品。生产环境推荐用 chrony。

对比项 ntpd chrony
收敛速度 慢,启动后需要几分钟才稳定 快,几秒内就能同步
大偏差处理 偏差 > 128ms 时拒绝调整 能处理任意大小的偏差
网络断开后 漂移较快 内部跟踪漂移率,断网后也能保持较长时间准确
最小同步间隔 固定 自适应,根据漂移情况动态调整
内存占用 较大 很小
是否推荐 传统环境 现代 Linux 发行版默认(RHEL 7+、Ubuntu 18.04+)

3.4 chrony 配置示例

# /etc/chrony/chrony.conf

# 上游时间服务器(建议配 3~4 个,互为校验)
server ntp.aliyun.com iburst minpoll 4 maxpoll 10
server cn.pool.ntp.org iburst minpoll 4 maxpoll 10
server time.windows.com iburst minpoll 4 maxpoll 10

# 允许 chrony 在大偏差时直接跳变(而不是缓慢调整)
# 生产环境慎用——跳变会导致基于 REALTIME 的计算出错
makestep 1.0 3

# 允许 chrony 跟踪硬件 RTC,重启后用 RTC 做初始估计
rtcsync

# 允许 drift(漂移率)记录到文件,重启后恢复
driftfile /var/lib/chrony/drift

# 日志
logdir /var/log/chrony

参数解释:

  • iburst:启动时快速发 4 个请求,加快初始同步。
  • minpoll 4:最小轮询间隔 2^4 = 16 秒。
  • maxpoll 10:最大轮询间隔 2^10 = 1024 秒(约 17 分钟)。chrony 会在这个范围内自适应。
  • makestep 1.0 3:如果偏差超过 1 秒,前 3 次同步允许直接跳变。之后只允许缓慢调整(slew)。

3.5 验证同步状态

# 查看同步状态
chronyc tracking

# 输出示例:
# Reference ID    : A1A2A3A4 (ntp.aliyun.com)
# Stratum         : 3
# System time     : 0.000123456 seconds fast of NTP time
# Last offset     : +0.000045678 seconds
# RMS offset      : 0.000098765 seconds
# Frequency       : 5.678 ppm fast
# Update interval : 64.7 seconds
# Leap status     : Normal

# 关键指标:
# System time  — 当前时钟与 NTP 标准的偏差
# RMS offset   — 偏差的均方根,反映同步稳定性
# Frequency    — 本地晶振的漂移率,chrony 在持续补偿这个值
# 查看各上游源的状态
chronyc sources -v

# 输出示例:
# MS Name/IP address         Stratum Poll Reach LastRx   Last sample
# ===================================================================
# ^* ntp.aliyun.com                2   10   377   45m   +23ms[+25ms] +/- 12ms
# ^+ cn.pool.ntp.org               2   10   377   45m   -18ms[-16ms] +/- 18ms
# ^- time.windows.com              2   10   377   45m   +45ms[+47ms] +/- 25ms

# ^* = 当前选中的同步源
# ^+ = 备选源
# ^- = 被排除的源(偏差太大)
# Reach = 377 (八进制) = 0b11111111,表示最近 8 次请求全部成功

4. PTP:需要更高精度时

4.1 什么时候需要 PTP?

场景 需要的精度 方案
普通业务服务器 10~50ms NTP / chrony
数据库集群 1~10ms NTP / chrony(配本地 NTP 源)
金融交易撮合 < 1ms PTP
5G 基站同步 < 1μs PTP + GPS
高频交易(HFT) < 100ns PTP + GPS + 硬件时间戳

4.2 PTP vs NTP 的核心区别

NTP:  软件时间戳,精度受协议栈延迟抖动限制
      精度: 毫秒级

PTP (IEEE 1588):  硬件时间戳,在网卡 PHY 层打时间戳
                  消除了操作系统协议栈的不确定延迟
                  精度: 亚微秒级

PTP 通过 Pdelay 机制测量链路延迟的不对称性,并补偿这个不对称——这是 NTP 做不到的(NTP 假设链路对称)。

4.3 PTP 的部署要求

  • 网卡支持硬件时间戳:需要支持 IEEE 1588 的网卡(如 Intel i210、Mellanox ConnectX 系列)。
  • 交换机支持 PTP:边界时钟(Boundary Clock)或透明时钟(Transparent Clock),否则交换机引入的排队延迟会破坏精度。
  • 全网链路 PTP 使能:任何一跳不支持,精度就在那一跳退化到软件时间戳水平。

普通业务服务器不需要 PTP。NTP/chrony 配置得当,精度足够覆盖 99% 的场景。


5. 生产环境最佳实践

5.1 架构:不要让所有服务器都去公网同步

                    ┌─────────────┐
                    │  公网 NTP    │
                    │  (Stratum 1) │
                    └──────┬──────┘
                           │
                    ┌──────▼──────┐
                    │ 内网 NTP 主  │  ← 2~3 台,专门做时间服务器
                    │ (Stratum 2) │     可以绑 GPS 授时卡
                    └──┬───┬───┬──┘
                       │   │   │
              ┌────────┘   │   └────────┐
         ┌────▼────┐  ┌────▼────┐  ┌────▼────┐
         │ 业务机 A │  │ 业务机 B │  │ 业务机 C │  ← 全部从内网 NTP 同步
         └─────────┘  └─────────┘  └─────────┘

好处:

  • 业务机不依赖公网可达性,公网断了内网时间仍然准(内网 NTP 有本地 RTC 和漂移记录兜底)。
  • 减少公网 NTP 流量(人家也是免费服务,别滥用)。
  • 内网延迟对称性好,同步精度更高。

5.2 内网 NTP 服务器的配置

# /etc/chrony/chrony.conf (内网 NTP 服务器)

# 上游用公网 NTP
server ntp.aliyun.com iburst
server cn.pool.ntp.org iburst

# 允许内网客户端来同步
allow 10.0.0.0/8

# 作为 NTP 服务器,即使自己还没同步好,也对外提供服务
# (否则所有客户端都拒绝同步,形成"全集群不同步"的死锁)
local stratum 5

# 如果有 GPS 授时卡(如 /dev/gps0),可以绑上去
# refclock PHC /dev/ptp0 poll 2 dpoll 2 offset 0 trust prefer

5.3 业务服务器的配置

# /etc/chrony/chrony.conf (业务服务器)

# 只从内网 NTP 同步,配 2~3 台互为备份
server 10.0.0.10 iburst minpoll 4 maxpoll 8
server 10.0.0.11 iburst minpoll 4 maxpoll 8
server 10.0.0.12 iburst minpoll 4 maxpoll 8

# 不对外提供 NTP 服务
deny all

# 漂移记录
driftfile /var/lib/chrony/drift
rtcsync

5.4 监控:你必须监控时钟偏差

不监控就等于没同步——你不知道哪台机器偷偷漂走了。

# 用 chronyc 获取偏差,推送到监控系统
OFFSET=$(chronyc tracking | grep "System time" | awk '{print $4}')
# 推送到 Prometheus / Zabbix / CloudWatch

告警阈值建议:

级别 偏差阈值 动作
正常 < 50ms 无
警告 50ms ~ 500ms 告警通知,不自动处理
严重 > 500ms 告警 + 自动重启 chrony
紧急 > 5s 告警 + 摘除节点(停止调度流量到此机器)

5.5 虚拟机的额外注意事项

# KVM 虚拟机: 确保宿主机开启 kvm-clock
# 宿主机 qemu-kvm 参数加: -rtc base=utc,clock=host
# 这让 VM 直接用宿主机的时钟,减少一层漂移

# VMware 虚拟机: 安装 VMware Tools,开启 Tools 同步
#   vmware-toolbox-cmd timesync enable

# AWS EC2: 默认提供 Amazon Time Sync Service
#   server 169.254.169.123 prefer iburst minpoll 4 maxpoll 10
#   这是一个 Stratum 1 源,免费且每个可用区都有

# 华为云 ECS: 可使用华为云内网 NTP
#   server ntp.myhuaweicloud.com iburst

6. 常见问题排查

6.1 chrony 启动后一直不同步

# 检查 1: UDP 123 端口是否被防火墙挡了
chronyc sources
# 如果 Reach 是 0,说明请求发不出去

# 检查 2: 上游服务器是否可达
nc -uv ntp.aliyun.com 123

# 检查 3: 系统是否装了多个时间同步服务(ntpd 和 chronyd 冲突)
systemctl status ntpd
systemctl status chronyd
# 只能运行一个!

# 检查 4: SELinux 是否阻止了 chrony
getsebool -a | grep chrony

6.2 时钟反复跳变,不稳定

# 检查 makestep 配置——如果阈值太低,chrony 会频繁跳变
# 修正: 提高 makestep 阈值,或去掉 makestep 让 chrony 只做 slew(缓慢调整)
# makestep 10 0  # 只在偏差 > 10s 时跳变,且只跳一次

# 检查上游源是否互相矛盾
chronyc sources
# 如果多个源的 Last sample 偏差方向不一致,说明某个源本身不准
# 去掉不靠谱的源

6.3 容器内时间不准

# Docker 容器默认共享宿主机的时钟,不需要单独同步
# 但如果容器内 chrony 和宿主机 chrony 冲突:
#   容器内不要装 chrony,直接用宿主机的时间
# 
# 如果宿主机时间不准,容器里怎么调都没用——先修宿主机

# Kubernetes: 确保所有 Node 的时间同步
# 在 DaemonSet 里跑一个检查脚本,发现偏差就告警

6.4 跨时区问题

# 服务器统一用 UTC,不要用本地时区
timedatectl set-timezone UTC

# 应用代码里:
# - 存储、计算、日志: 用 UTC
# - 展示给用户: 在前端/接口层转成用户时区
# - cron 表达式: 注意 cron 用的是系统时区,如果系统是 UTC,
#   "每天凌晨 2 点执行" 要写成 "0 18 * * *"(北京时间凌晨 2 点 = UTC 18 点)

7. 一张图总结

服务器时间对齐
├── 为什么重要
│   ├── TLS 证书校验
│   ├── 数据库复制
│   ├── 分布式锁
│   ├── 日志排序
│   └── 定时任务
│
├── 为什么不准
│   ├── 晶振公差 + 温度漂移 + 老化
│   ├── REALTIME vs MONOTONIC
│   └── 虚拟化额外漂移
│
├── 同步方案
│   ├── NTP / chrony(毫秒级,覆盖 99% 场景)
│   └── PTP(亚微秒级,需硬件支持)
│
├── 生产实践
│   ├── 内网 NTP 分层架构
│   ├── 配 3+ 个上游源互验
│   ├── 监控偏差 + 分级告警
│   └── 虚拟机/容器特殊处理
│
└── 排查清单
    ├── 端口/防火墙
    ├── 服务冲突
    ├── makestep 频繁跳变
    └── 时区统一用 UTC
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。