此 blog 转载自一个大神 starlitxiling NTP(Network Time Protocol)是一种广泛使用的时间同步协议,旨在通过网络将计算机时钟同步到UTC(Coordinated Universal Time),目的是为了解决不同系统之间时间一致性的问题,可以看一下这个典型的时钟同步算法 工作原理

场景:在分布式系统中,往往使用NTP来实现时间同步,这样可以让依赖时间戳的处理变得正确。

NTP的时间戳是从1900年1月1日开始计算的,NTP时间戳是64位值,其中高32位用于秒,低32位用于秒的小数部分,所以如果从NTP服务器获取时间戳,会得到一个1900年以来的总秒数,你可以用以下程序将一个NTP时间戳转换为ns级,然后和获取到的UTC时间进行比较,计算延迟

unsigned long long send_timestamp = read_dora_input_timestamp(event);  # 这里获得的是封装后的从1970年1月1日开始的NTP时间
unsigned long long seconds = send_timestamp >> 32;
unsigned long long fraction = send_timestamp & 0xFFFFFFFF;
unsigned long long seconds_ns = seconds * 1000000000LL;
unsigned long long fraction_ns = (fraction * 1000000000LL) / 4294967296LL;
unsigned long long result = seconds_ns + fraction_ns;

然后和UTC时间进行计算,如下:

struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
unsigned long long receive_timestamp = (unsigned long long)ts.tv_sec * 1000000000LL + ts.tv_nsec;
unsigned long long latency = receive_timestamp - result;
printf("Latency: %llu ns\n", latency);

在这里的clock_gettime因为传入的是CLOCK_REALTIME,所以获取的是1970年1月1日到现在的时间,具体的参数信息可以查阅man page

时间格式 起始时间 位数含义(单位是bit)
NTP 1900年1月1日 高32位是秒,低32位是纳秒
UNIX 1970年1月1日 高64位是秒,低64位是纳秒

在Linux系统中,你可以使用

sntp time.pool.aliyun.com #查看当前时间和服务器事件的事件偏差
sntp -s time.pool.aliyun.com # 突然调整服务器时间

这里挂一些其他的时间协议: