“一秒”宕机一个半小时!这个让程序员抓狂的续一秒,今年无了!

2024-07-10 13:54:00 浏览数 (2)

国际地球自转服务(IERS)宣布 2024 年世界时将不增加闰秒。对计算机系统和维护它的程序员而言,这是一个好消息。 最迟不晚于 2035 年前,闰秒就会被彻底废除。没有办法解决闰秒引发的问题,解决闰秒本身就不再有问题,毕竟人类对多出来的这一秒并无体感。本文将为你介绍闰秒的来源及其影响,并介绍各类系统常见的闰秒处理方法。

01、闰秒,程序员不能承受之重

人类对闰秒的调整体感上不可知,但对需要精准计时的计算机系统和互联网来说,简单粗暴的“加一秒”却没有好处,全是问题。 1972 年被首次引入至今,一共增加过 27 个正闰秒,每一次增加闰秒,就会引发软件行业的问题。 2012 年闰秒的引入让 Reddit 系统宕机一个半小时; 同年澳大利亚航空公司的办理系统也宕机数小时,被迫人工检查登机; 2017 年 Cloudflare 部分客户服务器因此离线; …… 为什么会有闰秒的存在?闰秒为什么会成为一个技术难题?目前我们都是怎么处理闰秒问题的?取消闰秒未来会带来哪些影响?本文将详细为你解读。

02、闰秒从何而来

世界上有几种计量时间的方式:

世界时(UT1):是一种天文计量的方式,天文学家通过观测地球的自转,并将自转一周的时间(一天)等分为86400份,每份为一秒,受潮汐等因素的影响,地球自转一周的时间并不是恒定的,这也是造成闰秒现象的直接原因。

原子时(TAI):由于上面描述的世界时并不稳定,物理学家用更为稳定的量子计量的方式来统计时间,1967年,国际计量大会用铯133(Cs133)原子基态的两个超精细能级之间的跃迁所对应辐射的9192631770个周期所持续的时间定义为1秒,这个是目前最精确的时间计量方式,其误差为1400000年一秒,基本可忽略不计。

协调世界时(UTC):又称世界标准时间或世界协调时间,UTC 以 TAI 为基础,又要兼顾 UT1,当 UTC,和 UT1 之间的偏差接近1秒时,国际地球自转和参考系服务(IERS)会提前6个月公布下一次闰秒的时间。

我们将世界绝大多数地方时区的基本时间称为协调世界时,即 UTC。它源自分布在世界一些国家的大量原子时钟。地球的自转并不是非常恒定的,有时会有一些变化,平均自转速度会缓慢下降。这就是为什么会在 UTC 时标中插入所谓闰秒,它们可将 UTC 时间进程调整到真实地球自转时间。

为什么会多出这一秒呢?它的存在是因为决定昼夜更替的地球绕轴自转会在很长的一段时间内慢下来,主要是由月亮-太阳引力造成。另外,地球也受其内部(地核、地幔)和外部(气候、海洋)构成影响。目前,时间主要由分属几个国家的 250 台原子时钟测量,这些原子钟是通过测量原子的能量转换水平工作。使用这些时钟计算 UTC,同时因为这个时间测量原理周期性地与地球不同步,因此必须使用闰秒进行校正。另外,我们必须考虑到现在的一天比 1820 年的一天要长 2 毫秒。不出所料,地球自转慢慢就与 UTC 不同步了。

国际地球自转服务局 IERS 测量的是真实地球自转,并决定何时插入闰秒。插入闰秒一般总是在某个月的最后一天进行,首选六月或十二月的 UTC 午夜时间。过去每次添加闰秒都是在六月或十二月进行。是否添加闰秒的声明,会由 IERS 在其 Bulletin C 中发布。目前,在可能添加闰秒日期前半年会公布 Bulletin C 。

因为闰秒是在全世界同时插入,插入闰秒的本地(民用)时间取决于本地时间与 UTC 之间的偏差,例如:2015年7月1日发生闰秒时,在时区 UTC 8h(北京时间) 中,闰秒会在时钟显示午夜后 8 小时的时候插入。

闰秒时计算北京时间的标准方法为:

代码语言:javascript复制
2015-07-01 07.59.57
2015-07-01 07.59.58
2015-07-01 07.59.59
2015-07-01 07.59.60 <-- 闰秒
2015-07-01 08.00.00
2015-07-01 08.00.01
2015-07-01 08.00.02

如果系统时钟采用国际原子时(TAI),并使用正确的时区,那么就会列出 23:59:60。但因为在 Unix 的 UTC 使用中不存在 23:59:60,Linux 内核会采用倒回一秒的方法在 0:00 UTC 后第一次时钟更新时插入闰秒。在本地时间计时中,根据不同的时区偏差,比如 UTC 8h,在 TencentOS Server 系统中,你会观察到以下现象:

代码语言:javascript复制
2015-07-01  07:59:58.000
2015-07-01  07:59:58.500
2015-07-01  07:59:59.000
2015-07-01  07:59:59.500
2015-07-01  08:00:00.000 <-- 插入闰秒
2015-07-01  07:59:59.000
2015-07-01  07:59:59.500
2015-07-01  08:00:00.000
2015-07-01  08:00:00.500

IERS 确定闰秒后,一些时间传播服务还会发布闰秒通知。这包括德国长波发射机 DCF77 和卫星巡航系统 GPS 示例。因此,可解码从那些系统获取信号的接收器也可以解码闰秒通知。如果在所应用协议中包含闰秒信息(例如接收器传送的时间字符串),则从那些接收器读取时间的应用程序也可以确定闰秒通知。请注意,时间代码接收器只能将闰秒通知转发到应用程序,同时正确计时。正确处理闰秒是应用程序和(/或)操作系统的任务。

从1972年到2020年,平均每21个月就插入一次闰秒。然而,间隔是非常不规则的,而且明显在增加。在1999年1月1日至2004年12月31日的六年中没有闰秒,但在1972-1979年的八年中有九个闰秒。自1972年协调世界时正式使用至今,全球已经实施了27次正闰秒调整,最近一次的闰秒调整是格林尼治时间2016年12月31日。从协调世界时正式使用以来,地球自转一直处于不断减慢的趋势,因此迄今为止的闰秒都是正闰秒。但相关科研发现,自2020年年中以来,地球自转速率呈现加快趋势,这意味着未来也可能会出现负闰秒。目前 TAI 与 UTC 的秒差为37:

代码语言:javascript复制
#  Value of TAI-UTC in second valid beetween the initial value until
#  the epoch given on the next line. The last line reads that NO
#  leap second was introduced since the corresponding date 
#  Updated through IERS Bulletin 64 issued in July 2022
#  
#
#  File expires on 28 June 2023
#
#
#    MJD        Date        TAI-UTC (s)
#           day month year
#    ---    --------------   ------   
#
    41317.0    1  1 1972       10
    41499.0    1  7 1972       11
    41683.0    1  1 1973       12
    42048.0    1  1 1974       13
    42413.0    1  1 1975       14
    42778.0    1  1 1976       15
    43144.0    1  1 1977       16
    43509.0    1  1 1978       17
    43874.0    1  1 1979       18
    44239.0    1  1 1980       19
    44786.0    1  7 1981       20
    45151.0    1  7 1982       21
    45516.0    1  7 1983       22
    46247.0    1  7 1985       23
    47161.0    1  1 1988       24
    47892.0    1  1 1990       25
    48257.0    1  1 1991       26
    48804.0    1  7 1992       27
    49169.0    1  7 1993       28
    49534.0    1  7 1994       29
    50083.0    1  1 1996       30
    50630.0    1  7 1997       31
    51179.0    1  1 1999       32
    53736.0    1  1 2006       33
    54832.0    1  1 2009       34
    56109.0    1  7 2012       35
    57204.0    1  7 2015       36
    57754.0    1  1 2017       37

03、闰秒处理方案

3.1 运行 NTP 的系统

系统如果使用 NTP(网络时间协议)守护进程(ntpd)将其本地计时与 NTP 服务器同步,则都应自动进行闰秒调整。进行闰秒调整的前一天,NTP 服务器应通知其客户端第二天的 23:59:59 UTC 会发生发生闰秒,Linux 内核应通过两次显示第 60 秒或彻底删除它,以便添加或者删除额外一秒。因此,在闰秒调整期间,运行 NTP 的系统应有如下计时显示:

代码语言:javascript复制
2015-06-30 23:59:59 UTC
2015-06-30 23:59:59 UTC
2015-06-30 00:00:00 UTC

发生闰秒时,内核会在系统 log 中写入信息:

代码语言:javascript复制
Jul  1 07:59:59 TENCENT64 kernel: [579201.951291] Clock: inserting leap second 23:59:60 UTC

使用 ntpdate 命令方式,与 ntp 服务器进行时间同步的系统,将不会通过 ntp 服务器接收到闰秒通知,而是在系统管理员指定的时刻与ntp服务器进行时间同步。例如,系统管理员设定每小时的第52分与 ntp 服务器进行时间同步,那么在7月1日08:00 CST 到09:52之间,系统时间与 ntp 服务器时间会相差1秒(快1秒)。

3.2 运行 PTP 的系统

PTP(精确时间协议)中交换的时间戳通常采用不包含闰秒的 TAI(国际原子时);但 ptp4l 和 phc2sys 将设置内核标签,插入闰秒以便系统时钟继续以 UTC 运行。然后该内核就可以正常插入闰秒。

3.3 未运行 NTP 或者 PTP 的系统

默认情况下,不使用 NTP 或者 PTP 同步其计时的 Linux 系统不会修正闰秒,且这些系统报告的时间与修正闰秒后的 UTC 时间有一秒钟的差别。闰秒发生后应手动重置时钟。

你还可以将 tzdata 更新至最新版本,将 /usr/share/zoneinfo/right 目录层级中的正确文件复制到 /etc/localtime,并将时钟重置到正确的本地时间,以便将这些系统配置可正确报告时间。 /usr/share/zoneinfo/right 中的文件包含自该世纪开始,从 1970 年 1 月 1 日 00:00:00 UTC 发生的所有闰秒修正的本地时间信息。 /usr/share/zoneinfo 中的其他时区文件未添加闰秒修正。从1972年至今,共添加了 27次闰秒。

例如:如果某个系统位于中国时区,你可以将其重新配置为通过运行以下命令报告闰秒修正时间,

代码语言:javascript复制
cp /usr/share/zoneinfo/right/Asia/Shanghai /etc/localtime

例如在 TS2 系统中,tzdata 包的版本为 tzdata-2015a-1.tl2.noarch,执行完上述拷贝后,则会在闰秒发生时间2015年7月1日8点自动插入闰秒。

3.4 windows 系统

早期的 Windows 版本(Win10版本以前) 时间服务并不表示 Leap 指标的值,当 Windows 时间服务接收到的数据包,包括闰秒。因此,闰秒发生后,正在运行 Windows 时间服务的 NTP 客户端会比实际时间快一秒。这种时间差异在下次同步时解决。

从 Windows 10 Redstone 5 和 Windows Server 2019 起,微软的操作系统能以更精确、UTC 兼容和可追踪的方式处理闰秒。不过从2017年至今,没有发生过闰秒了。

04、历史影响

对于日常生活而言,正常的上班、下班、工作、学习,生命中偏差的这一秒无关痛痒。然而闰秒对于精确要求时间的行业如航空、航天、军工等,会产生较大影响。对于服务器清一色 Linux 系统的互联网行业而言,闰秒可能会造成机器 CPU 突然增高,机器宕机、对应的服务挂掉。随着 Linux 的普遍使用,闰秒的影响也被越来越多的被关注。

历史上,因为 Linux 内核的一些问题,闰秒对系统造成多次影响。比如 CPU 利用率高会给生产环境带了不少挑战。2012年实施闰秒时,国外不少知名网站出现了临时服务中断。当2015年闰秒再度来临时,工程师们修复了部分2012年出现的问题,但却东窗事发——发现了新的问题。后续亦是如此。闰秒让互联网企业如鲠在喉。

这里简单列举一下在 Linux 内核版本中曾因闰秒所引发的各种问题:

  • Linux-2.6.22以前内核版本的闰秒死锁。
    • 07年的commit:http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=746976a301ac9c9aa10d7d42454f8d6cdad8ff2b;hp=872aad45d6174570dd2e1defc3efee50f2cfcc72
  • Linux-2.6.25到2.6.27内核版本的系统死锁。
  • Linux-3.4内核版本的系统活锁。
    • 08年的commithttps://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7dffa3c673fbcf835cd7be80bb4aec8ad3f51168
    • 12年的commit:https://lkml.org/lkml/2012/3/15/616
  • Linux-2.6.32内核插入闰秒可能出现高 CPU 消耗。

05、取消闰秒

5.1 为何取消闰秒

对闰秒最为敏感的莫过于计算机相关领域。由于闰秒的出现没有固定规律,对应的时间调整无法从一开始就写在计算机程序里。在万物互联时代,很多领域都依托计算机网络传输信息,实施闰秒也会影响航空、通信、金融及其他需要精准对时的领域。

此前 Meta 公司两名工程师发文称:“闰秒是一种弊大于利的冒险做法,我们认为现在是时候引入新技术来取代它了。”这一表态获得了互联网大厂的广泛赞同。

5.2 取消闰秒的后续可能

负责协调世界时的国际计量局(BIPM)表示,科学家和政府代表18日在法国举行的一次会议上投票决定到2035年取消闰秒。BIPM 时间部门负责人帕特里齐亚·塔维拉表示,这项“历史性决定”将允许“秒数连续流动,而不会出现目前由不规则闰秒造成的不连续性“。

闰秒是目前把世界时和国际原子时联系起来的手段。由于世界时是基于地球自转确定的,又称天文时或太阳时。没有闰秒意味着人们使用的时间与地球自转、太阳位置不关联,时间和天文学呈现割裂状态。

第27届国际计量大会决议要求多机构协商,提出一个可以将协调世界时持续至少百年的新方案并制定实施计划,纳入下一届大会的决议草案中。根据决议,闰秒将暂时继续正常添加。但到2035年,世界时和国际原子时之间的差异将被允许增长到大于一秒的值。

也许解决这个问题的可能方法是让世界时和国际原子时之间的差异增加到一分钟,但专家估计调整时长在50到100年之间。而有提议指出,无需在时钟上增加闰分钟,而是将某一天的最后一分钟变为需要两分钟;也有人建议停止校正,同时公布世界时和国际原子时之间不断增长的时刻差。

0 人点赞