聽過閏年閏月,聽過閏秒嗎?

語言: CN / TW / HK

閏年閏月大家都知道,可是你聽說過閏秒這回事情嗎?

閏年是為了彌補是我們的歷法365天和地球實際公轉365.25天的差距,所以每4年會一年是閏年,多出來的那一天就是2月29日。

閏月則是和陰曆有關,不同於陽曆的以公轉制定的方式,陰曆以月亮繞地球的時間來計算,所以會和陽曆的365.25天相差10天21小時,於是,多出來的時間累積下來湊成一個月,也就是閏月了。

那麼什麼是閏秒?閏秒會帶來什麼影響?怎麼解決閏秒帶來的問題?

閏秒定義

要了解閏秒,首先需要了解幾個基本的概念。

平均太陽日:天空中的太陽連續兩次出現最大仰角(90度)所經歷的時間就是一個太陽日,而又由於太陽日的長短不同,所以取一年內的太陽日平均值,所以可以大致的認為一個平均太陽日就是一天24小時。

UTC:英文為Coordinated Universal Time,中文叫做協調世界時或者世界標準時間,相信開發的同學都很清楚,他是世界上調節時鐘和時間的主要時間標準,也是最接近格林威治標準時間GMT的時間系統之一。

最早的時候,一秒根據平均太陽日的1/86400來定義,這個時間依賴於地球的自轉和公轉。後來直到1967年,秒被物理學重新定義,以銫133的振盪頻率來定義秒,並可以用原子鐘來測量。

UTC的時間就是基於此來定義,而且他是一個固定的時間長度。

但是由於地球自轉的速度受到潮汐加速等眾多因素的影響,平均太陽日的時間並不固定。

為了讓UTC貼近平均太陽日的時間,所以就產生了閏秒。

閏秒分為兩種形式:

  1. 正閏秒,也就是在23:59:59之後一秒是23:59:60,然後才是00:00:00,很奇葩很詭異是不是。
  2. 負閏秒,23:59:58的下一秒就是00:00:00,但是目前沒有出現過負閏秒。

閏秒的時間調整一般是在6月30日或者12月31日,而離我們最近的一次閏秒的調整則是在2016年的12月31日。

從1972年到現在,已經發生了20多次閏秒,對於我們的系統配置來說,通過NTP的服務來進行時間同步,如果伺服器收到閏秒的處理通知,則會一級級下發到最邊緣的NTP伺服器,然後通知到客戶端的作業系統,最終由作業系統來處理閏秒。

下面的表格是歷年發生閏秒的時間:

6月30日12月31日
1972年+1+1
1973年0+1
1974年0+1
1975年0+1
1976年0+1
1977年0+1
1978年0+1
1979年0+1
1981年+10
1982年+10
1983年+10
1985年+10
1987年0+1
1989年0+1
1990年0+1
1992年+10
1993年+10
1994年+10
1995年0+1
1997年+10
1998年0+1
2005年0+1
2008年0+1
2012年+10
2015年+10
2016年0+1

帶來的影響

雖然閏秒對普通人的日常生活沒有任何影響,但是對於開啟NTP服務的Linux系統來說有致命的風險,在Linux kernel 2.6.29之前版本存在bug,在進行閏秒調整時可能會引起系統導致ntpd程序死鎖,從而導致crash。另外由於應用程式不能處理閏秒的問題導致時間的變化,會導致CPU load激增。

在上一次閏秒產生,國外Reddit、Mozilla、FourSquare、Yelp、LinkedIn和Gawker都產生了一定的問題,其中Reddit宕機時間超過1個半小時。其中,或許你能很明顯的看到異常錯誤資訊:kernel[81951.244556] Clock: inserting leap second 23:59:60 UTC

另外,針對資料庫方面,23:59:60時間的問題相容也不盡相同。

PostgreSQL:PostgreSQL可以相容23:59:60的寫法,不會報錯。

Mysql:Mysql還不支援60秒寫法,閏秒時必須使用unix time來表示時間,否則會報錯。

根據目前的資訊來看,Linux核心版本高於2.6.29修復了這個問題,NTP版本高於4.2.2p1-9會把這一秒的時間分散到大約2000秒中,低於該版本的話則會直接加一秒或者減一秒。

解決方案

最簡單直接的方法就是閏秒發生前停止ntpd服務,閏秒結束後再開啟。

提前一天停止ntp /etc/init.d/ntpd stop
重置系統時間 date -s "`date`"
重新開啟ntp ntp/etc/init.d/ntpd start
複製程式碼

但是有一個很明顯的問題就是,大公司一個服務上千臺機器,操作起來成功太高,而且停止同步是否會帶來其他的問題不好評估影響面。

目前像google、阿里、amazon都有一些具體的應對方案,使用雲服務的話可能不需要使用者關心這方面的問題,如果是自己機房託管的話那麼可能需要運維開發人員手動處理了。

以國內阿里雲的處理方案舉例,amazon同樣也是採用該方案

阿里雲的ECS雲伺服器的NTP服務採用忽略閏秒時刻的跳秒,緩慢同步消除閏秒帶來的1秒誤差的方案來面對閏秒事件,實際上採用的方案是閏秒發生前,每秒比UTC慢1/86400,經過12小時(43200秒)後,會比UTC慢0.5秒,閏秒發生之後,每秒和UTC誤差減少1/86400,經過12小時(43200秒)後,-0.5的誤差消除。國外Amazon也是這樣的解決方案。

具體時間同步方案如下表格所示:

UTC阿里雲時間(北京時區阿里雲時間和UTC誤差備註
2016/12/31 11:59:592016/12/31 19:59:59+0和UTC完全同步
12:00:0020:00:00+0
12:00:01每秒比UTC慢1/86400,經過12小時(43200秒)後,會比UTC慢0.5秒
20:00:01+1/86400
12:00:02
20:00:02+2/86400
23:59:59
2017/1/1 07:59:59+43199/86400
23:59:60閏秒
2017/1/1 08:00:00-0.5秒和UTC誤差-0.5秒
2017/1/1 00:00:00每秒和UTC誤差減少1/86400,經過12小時(43200秒)後,-0.5的誤差消除
08:00:01-43199/86400
00:00:01
08:00:02-43198/86400
19:59:59-1/86400
11:59:59
2017/1/1 12:00:002017/1/1 20:00:000再一次和UTC同步
12:00:0120:00:010

如何預測避免

實際上,由於地球自轉的時間無法計算,他有可能變快,也有可能變慢,受到潮汐、天氣和熔態金屬在地球核心的流動等各方面因素的影響,下一次閏秒的時間無法預估,但是國際地球自轉和參考系服務(IERS)會提前6個月公佈下一次閏秒的時間。

巨人的肩膀:

zh.wikipedia.org/wiki/%E9%97…

developer.aliyun.com/article/682…

yq.aliyun.com/articles/80…

www.cnblogs.com/luxianghao/…

更多更新,請關注公眾號“艾小仙”