新闻、帮助、产品更新动态

最新的业界新闻,产品系统更新开发动态,帮助教程和活动发布

对于腾讯云2015年闰秒分析共享

发布日:2015-07-10 22:33       阅读数:

尊敬的腾讯云客户:
       您好!如下是腾讯云为大家提供闰秒分析,请查阅;业务如果希望完全避免闰秒问题带来的影响,可在2015年6月30日08点前先确认NTP服务已同步,然后关闭NTPD服务(闰秒通知和闰秒处理不是同时进行的,闰秒通知先行下发);在2015年7月1日8点后开启NTPD服务。
【注】linux受影响的内核版本:
         1) linux-2.6.22 之前内核版本;
           2) linux-2.6.25到2.6.27内核版本;
           3) linux-3.4内核版本;
           4) linux-2.6.32内核版本; 
 
1.背景:
       设在巴黎的国际地球自转学会近日表示,由于地球自转放缓的原因,2015年将迎来史上第26次闰秒,时间在6月30日午夜(北京时间7月1日早上8点),科学家们将再度给钟表额外增加1秒钟时间,届时原子钟将会在北京时间7月1日7点59分59秒后停留一秒钟,让变慢的地球自转跟上原子钟步伐。如果不对闰秒问题进行处理,会影响到时间敏感度高的业务。
       我们将世界绝大多数地方时区的基本时间称为协调世界时,即 UTC,它源自分布在世界一些国家的大量原子时钟。地球的自转并不是非常恒定的,有时会有一些变化,平均自转速度会缓慢下降。这就是为什么会在 UTC 时标中插入所谓闰秒的原因,它们可将 UTC 时间进程调整到真实地球自转时间。
        为什么会多出这一秒呢?它的存在时因为决定昼夜更替的地球绕轴自转会在很长的一段时间内慢下来,主要是由月亮-太阳引力造成。另外,地球也受其内部(地核、地幔)和外部(气候、海洋)构成影响。目前,时间主要由分属几个国家的 250 台原子时钟测量,这些原子钟是通过测量原子的能量转换水平工作。使用这些时钟计算 UTC,同时因为这个时间测量原理周期性地与地球不同步,因此必须使用闰秒进行校正。另外,我们必须考虑到现在的一天比 1820 年的一天要长 2 毫秒。不出所料,地球自转慢慢就与 UTC 不同步了。
        国际地球自转服务局,IERS 测量的是真实地球自转,并决定何时插入闰秒。插入闰秒一般总是在某个月的最后一天进行,首选六月或十二月的 UTC 午夜时间。过去每次添加闰秒都是在六月或十二月进行。有关是否添加闰秒的声明由 IERS 在其Bulletin C 中发布。目前,在可能添加闰秒日期前半年会公布 Bulletin C 。
        因为闰秒是在全世界同时插入,插入闰秒的本地(民用)时间取决于本地时间与 UTC 之间的偏差,例如:在时区 UTC+8h 中,闰秒会在时钟显示午夜后 8 小时的时候插入。
       闰秒时计算北京时间的标准方法为:
       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,您会观察到以下现象:
       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.0xx <-- 插入闰秒
       2015-07-01  07:59:59.0xx
       2015-07-01  07:59:59.500
       2015-07-01  08:00:00.000
       2015-07-01  08:00:00.500
       IERS 确定闰秒后,一些时间传播服务还会发布闰秒通知。这包括德国长波发射机 DCF77 和卫星巡航系统 GPS 示例。因此,可解码从那些系统获取信号的接收器也可以解码闰秒通知。如果在所应用协议中包含闰秒信息(例如接收器传送的时间字符串),则从那些接收器读取时间的应用程序也可以确定闰秒通知。请注意,时间代码接收器只能将闰秒通知转发到应用程序,同时正确计时。正确处理闰秒是应用程序和(/或)操作系统的任务。
 
2. 闰秒处理
2.1 运行NTP的系统
      系统如果使用 NTP(网络时间协议)守护进程(ntpd)将其本地计时与 NTP 服务器同步,则都应自动进行闰秒调整。进行闰秒调整的前一天,NTP 服务器应通知其客户端第二天的23:59:59 UTC 会发生发生闰秒,Linux 内核应通过两次显示第 60 秒或彻底删除它,以便添加或者删除额外一秒。因此,在闰秒调整期间,运行 NTP 的系统应有如下计时显示:
2015-06-30 23:59:59 UTC2015-06-30 23:59:59 UTC2015-06-30 00:00:00 UTC
发生闰秒时,内核会在系统 log 中写入信息。
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秒)。
2.2 运行PTP的系统
      PTP(精确时间协议)中交换的时间戳通常采用不包含闰秒的TAI(国际原子时);但 ptp4l和 phc2sys 将设置内核标签,插入闰秒以便系统时钟继续以 UTC 运行。然后该内核就可以正常插入闰秒。
2.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 中的其他时区文件未添加闰秒修正。 2008 年闰秒后,本世纪共添加了 25 次闰秒。
例如:如果某个系统位于中国时区,您可以将其重新配置为通过运行以下命令报告闰秒修正时间,
cp /usr/share/zoneinfo/right/Shanghai /etc/localtime
例如在tlinux2.0系统中,tzdata包的版本为tzdata-2015a-1.el7_0.noarch,执行完上述拷贝后,则会在2015年7月1日8点自动插入闰秒。
2.4  windows系统
       Windows 时间服务并不表示 Leap 指标的值,当 Windows 时间服务接收到的数据包,包括闰秒。因此,闰秒发生后,正在运行 Windows 时间服务的 NTP 客户端会比实际时间快一秒。这种时间差异在下次同步时解决。
 
3. 影响
3.1 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
       每次时钟中断触发时会调用 tick_do_update_jiffies64 更新 jiffies 的 值。因此在更新前对xtime_lock 加了写锁。闰秒产生时,需要修正一下 jiffies 的值,所以在tick_do_update_jiffies64 里面最终会调用到 second_overflow 这个函数处理润秒。在函数second_overflow 里面,处理润秒的增加和减少前都调用了一个 clock_was_set 函数。该函数内部,请求了 xtime_lock 的读锁。此时,与先前的写锁发生死锁。
       该patch在linux内核版本2.6.22中引入,所以只有2.6.22内核之前的系统可能出现该问题,因而只可能影响sles10和centos5.5系统。但是,在sles10和centos5.5中,clock_was_set()因不支持高精度时钟而被定义为空,所以不造成影响。
3.2 linux-2.6.25到2.6.27内核版本的系统死锁
      Bug 479765 - Leap second message can hang the kernel 描述了leap second会对系统产生影响的原因:
      当一个leap second被插入或删除时,内核会打印一条相关信息:
      [69596.647516] Clock: inserting leap second 23:59:60 UTC
       而该信息的打印会因xtime_lock而造成系统死锁。
      下面是2.6.26内核下该问题出现时的栈信息(this is with Fedora 8 and
kernel kernel-2.6.26.6-49.fc8.x86_64):
#0  ktime_get_ts (ts=0ffffffff8158bb30) at include/asm/processor.h:691
#1  0ffffffff8104c09a in ktime_get () at kernel/hrtimer.c:59
#2  0ffffffff8102a39a in hrtick_start_fair (rq=0ffff810009013880, 
    p=<value optimized out>) at kernel/sched.c:1064
#3  0ffffffff8102decc in enqueue_task_fair (rq=0ffff810009013880, 
    p=0ffff81003fb02d40, wakeup=1) at kernel/sched_fair.c:863
#4  0ffffffff81029a08 in enqueue_task (rq=0ffffffff8158bb30, 
    p=0ffff81003b8ac418, wakeup=-994836480) at kernel/sched.c:1550
#5  0ffffffff81029a39 in activate_task (rq=0ffff810009013880, 
    p=0ffff81003b8ac418, wakeup=20045) at kernel/sched.c:1614
#6  0ffffffff8102be38 in try_to_wake_up (p=0ffff81003fb02d40, 
    state=<value optimized out>, sync=0) at kernel/sched.c:2173
#7  0ffffffff8102be9c in default_wake_function (curr=<value optimized out>, 
    mode=998949912, sync=20045, key=04c4b40000) at kernel/sched.c:4366
#8  0ffffffff810492ed in autoremove_wake_function (wait=0ffffffff8158bb30, 
    mode=998949912, sync=20045, key=04c4b40000) at kernel/wait.c:132
#9  0ffffffff810296a2 in __wake_up_common (q=0ffffffff813d3180, mode=1, 
    nr_exclusive=1, sync=0, key=0x0) at kernel/sched.c:4387
#10 0ffffffff8102b97b in __wake_up (q=0ffffffff813d3180, mode=1, 
    nr_exclusive=1, key=0x0) at kernel/sched.c:4406
#11 0ffffffff8103692f in wake_up_klogd () at kernel/printk.c:1005
#12 0ffffffff81036abb in release_console_sem () at kernel/printk.c:1051
#13 0ffffffff81036fd1 in vprintk (fmt=<value optimized out>, 
    args=<value optimized out>) at kernel/printk.c:789
#14 0ffffffff81037081 in printk (
    fmt=0ffffffff8158bb30 "yj$\201????\2008\001\t") at kernel/printk.c:613
#15 0ffffffff8104ec16 in ntp_leap_second (timer=<value optimized out>)
    at kernel/time/ntp.c:143
#16 0ffffffff8104b7a6 in run_hrtimer_pending (cpu_base=0ffff81000900f740)
    at kernel/hrtimer.c:1204
#17 0ffffffff8104b86a in run_hrtimer_softirq (h=<value optimized out>)
    at kernel/hrtimer.c:1355
#18 0ffffffff8103b31f in __do_softirq () at kernel/softirq.c:234
#19 0ffffffff8100d52c in call_softirq () at include/asm/current_64.h:10
#20 0ffffffff8100ed5e in do_softirq () at arch/x86/kernel/irq_64.c:262
#21 0ffffffff8103b280 in irq_exit () at kernel/softirq.c:310
#22 0ffffffff8101b0fe in smp_apic_timer_interrupt (regs=<value optimized out>)
    at arch/x86/kernel/apic_64.c:514
#23 0ffffffff8100cf52 in apic_timer_interrupt ()
    at include/asm/current_64.h:10
#24 0ffff81003b9d5a90 in ?? ()
#25 00000000000000000 in ?? ()
       从上面的栈信息我们可以发现:该问题的出现原因在于当对leap second进行操作(插入或删除)之前,已经获取了xtime_lock锁;而之后在调用printk()打印日志信息时,printk()中会尝试唤醒klogd内核线程,在唤醒过程中会调用到公平调度类的相关函数,其中会调用ktime_get()获取时间信息,其中会再次尝试获取xtime_lock锁,从而造成死锁。
       该问题部分来源于hrtick_start_fair()函数的引入。是由commit 8f4d37ec (high-res preemption tick)引发,大概在2.6.25引入。所以在2.6.25之前的内核,不会发生这个死锁。
       而在2.6.28, 引入了commit b845b517,printk()中的wake_up_klogd()不会直接wake_up klogd()也就不会触发后续的xtime_lock,也就避免了死锁的发生。
      所以,该原因引起的系统死锁只可能发生在linux内核2.6.25到2.6.27版本下。
Sles11使用2.6.27内核,属于比较危险的部分内核。但是Novell声称已经引入了commit b845b517b5e3706a3729f6ea83b88ab85f0725b0,因而不存在该问题,而且几个小时的实验后系统仍然正常。
      此问题影响的版本还有 RHEL4:kernel-2.6.9.89.EL之前的版本,RHEL5.3:kernel-2.6.18-128.37.1.el5之前的版本。现网centos5.5使用的内核版本是2.6.18-194.el5,其不受影响。
3.3 linux-3.4内核版本的系统活锁
      08年的commit:https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7dffa3c673fbcf835cd7be80bb4aec8ad3f51168中为了解决之前遇到的leap second问题而将对leap second的处理从second_overflow()中独立出来,使用定时器来完成此工作。但是12年的commit:https://lkml.org/lkml/2012/3/15/616
认为该patch存在如下可能的livelock场景:
CPU 0                                                                         CPU 1
do_adjtimex()
spin_lock_irq(&ntp_lock);
process_adjtimex_modes();                                   timer_interrupt()
process_adj_status();                                        do_timer()
ntp_start_leap_timer();                                     write_lock(&xtime_lock);
hrtimer_start();                                             update_wall_time();
hrtimer_reprogram();                                     ntp_tick_length()
tick_program_event()                                     spin_lock(&ntp_lock);
clockevents_program_event()
ktime_get()
seq = req_seqbegin(xtime_lock);
      问题在于,引入ntp_lock的commit:http://patches.linaro.org/5122/是在3.4内核才引入的,且在3.4内核得到了修复,因此此问题对3.4以前和以后的内核无影响。
3.4 linux-2.6.32内核插入闰秒可能出现高CPU消耗
      2012年的闰秒插入当时导致了一些互联网公司的服务器高cpu消耗,其问题根源在以下网址得到了阐述:https://lkml.org/lkml/2012/7/1/203。
   
3.5 总结
     总的来说,闰秒的插入对各主要发行版的影响包括:
     1) Centos5.5(原生内核),SUSE Linux Enterprise Server 10,Tencent tlinux release 2.0,windows2003,windows2008,基本无影响。
     2)Suse11(2.6.27内核)有潜在影响(见3.2),目前实验验证无影响。
     3.)Tlinux-suse,Tencent tlinux release 1.2(2.6.32内核)有潜在影响(见3.4),闰秒插入后在特定情况下可能会出现高CPU消耗,可使用3.4节小程序来设置自动解决。
     4.)使用ntpdate方式同步时间的服务器基本无影响,使用ntpd方式同步时间的服务器,或者使用了较新的tzdata(2015版本以上)的服务器,才有可能受到闰秒问题影响。
     5)对时间精度要求较高的业务,请在闰秒发生后,及时得与时间服务器进行时间校准。
     6)使用其他操作系统的业务,可通过运行3.4小节的测试程序,来模拟闰秒的插入对系统的影响。
业务如果希望完全避免闰秒问题带来的影响,可在2015年6月28日24点前先确认NTP服务已同步,然后关闭NTPD服务(闰秒通知和闰秒处理不是同时进行的,闰秒通知先行下发);在2015年7月1日8点后开启NTPD服务。
 
4.如何避免闰秒
业务如果希望完全避免闰秒问题带来的影响,可在2015年6月30日08点前先确认NTP服务已同步,然后关闭NTPD服务(闰秒通知和闰秒处理不是同时进行的,闰秒通知先行下发);在2015年7月1日8点后开启NTPD服务。
 
关键词: 腾讯云 共享

编辑:航网科技   来源:深圳航网科技有限公司

本文版权归原作者所有 转载请注明出处

联系我们

客服部:深圳市龙华区龙胜商业大厦5楼B5区

业务部:深圳市南山区讯美科技广场2栋12楼1202

资质证书

  • Copyright © 2011-2020 www.hangw.com. All Rights Reserved 深圳航网科技有限公司 版权所有 增值电信业务经营许可证:粤B2-20201122 - 粤ICP备14085080号

    在线客服

    微信扫一扫咨询客服


    全国免费服务热线
    0755-36300002

    返回顶部