計算機時間到底是怎麼來的?程序員必看的時間知識!
大家好,我是 Kaito。
這篇文章我想和你聊一聊「時間」這個話題。
時間總是在不經意間流逝,我們在寫代碼時,也經常會調用「時間 API」,你有思考過這背後的原理嗎?
關於時間的問題還有很多,例如:
-
爲什麼計算機的時間有時候「走不準」?
-
計算機究竟是怎麼「自動校準」時間的?
-
我們經常看到的 UTC 時間,到底是什麼?
-
我們在新聞上看到的「北京時間」,真的來自北京嗎?
這篇文章,我們就來揭祕時間背後的祕密。
這篇文章非常有意思,希望你可以耐心讀完。
時間爲什麼總是走 “不準”?
你肯定遇到過這樣的場景,家裏買了一個鐘錶,時間一長,就會發現它走得「不準」了。
又或者,一臺長時間不使用的電腦,它的時間也會發生偏差。
遇到這些情況,你可能會不以爲然。時間不準,那我們就「人工」調準它。
但你有沒有停下來想一想,爲什麼它們的時間會越走越不準呢?
要回答這個問題其實不難,我們只需要搞清楚,它們的時間是怎麼來的。
鐘錶和計算機內部都有一個叫做「晶體振盪器」的東西,給它加上電壓,它就會以固定的頻率振動。但這個振動頻率的「穩定性」,取決於它的製造工藝,以及外界環境的影響。
出於成本的考慮,鐘錶的製作工藝沒那麼高,所以它更容易有誤差。而電腦製造工藝雖然比較高,但它內部的晶體振盪器也會受到「溫度」變化帶來的影響,在工作過程中,也會有產生誤差。
雖然它們的誤差很小,但日積月累下來,誤差就越來越明顯。
因此,我們現在使用的計算機,都有「自動校準」時間的功能。但是如何校準呢?
如何校準時間?
很簡單,只要你把電腦連上了「網絡」,你會發現,它會自動與「網絡時間」保持同步。
可問題是,這個「網絡時間」哪兒來的?
我猜你大腦的第一反應是,每臺電腦肯定配置了一個「時間服務器」,之後這臺電腦會與服務器定時同步,自動校準。
沒錯,確實是這樣,不光是電腦,我們平時使用的手機、平板、智能手錶等電子設備,只要能連接網絡,都會自動同步網絡時間。
那繼續追問,這個「時間服務器」的時間就一定是準的嗎?
理論來講,它應該也是一臺計算機,難道它不會遇到我們前面說的問題嗎?
此外,這個網絡時間究竟是怎麼「同步」到我們的電腦上的?
你可能會說,那肯定是通過網絡數據包。
問題又來了,網絡傳輸數據也是有「延遲」的,同步服務器時間,不還是存在誤差嗎?
環環相扣,像一個俄羅斯套娃,很難解釋清楚。
要想徹底搞清楚這些問題,就要深入到時間的「源頭」來尋找答案。
時間是怎麼來的?
時間是一個非常抽象的概念,多少年來,吸引着無數科學家、物理學家、甚至哲學家花費畢生精力去解釋時間的本質是什麼,從宇宙大爆炸到時空相對論,從黑洞到量子力學,都能看到關於時間這個問題的身影。
這裏我們不探討高深莫測的學術知識,只把目光放聚焦在計算機這個很小的範疇內。但要想清楚解釋這個問題,也並非想的那麼簡單。
我們從最簡單的開始說起。
想要知道時間是怎麼被定義的,首先要知道「天」是怎麼來的?
答案是:觀察太陽。
由於地球的「自轉」,人們可以看到日出日落,人們日出而作,日落而息,所以就把這一週期現象定義爲「天」。
地球除了自轉,還在圍繞太陽公轉,所以公轉一週就被定義爲一「年」。
從這些現象就能看出來,很早之前的人們,是以「天文現象」來確定時間的。
再後來,人們爲了把時間定義得更「精確」,就把一天平均劃分爲 24 等份,這就是「時」。
同樣地,把 1 小時劃分 60「分鐘」,1 分鐘劃分爲 60「秒」。
這樣,時間的基本單位「秒」就被定義出來了。
所以,秒與天的關係就是這樣的:
1 秒 = 1 / 24 * 60 * 60 = 1 / 86400 天。
這些定義,都與「地球自轉」和「太陽」息息相關。
但是,後來人們發現,地球的公轉軌道並不是一個正圓,而是一個「橢圓」,也就是說公轉速度是「不均勻」的,這意味着什麼呢?
這意味着每天的時間不是等長的,那根據天推算出的秒,自然也不是「等長」的。
很明顯,這裏的計算存在誤差。這怎麼辦?
聰明的人們就想到,把一年內所有天的時長加起來,然後求「平均」,得到相對固定的「天」,然後再計算得出「相對平均」的秒,這樣就減小了誤差。
確定了天文規律,人們開始製造「鐘錶」,把時間表示出來。
從擺鐘到機械鐘,再到現代廣泛使用的石英鐘,鐘錶的製作工藝越來越高,時間精度也越來越高,現代石英鐘每天的計時誤差只有「千分之一秒」。
所以,在 1927 年,人們以基於「天文現象」+「鐘錶計時」,確立了第一套時間標準:世界時(Universal Time,簡稱 UT)。
但是,隨着科技的發展,人類對太陽的觀測越來越精準,有意思的事情發生了。
人們發現,地球每天的自轉速度也「不是勻速」的,地球的自轉受到潮汐、地殼運動、冰川融化、地震等自然現象的影響,越來越慢!
這會導致什麼問題呢?
這會導致之前規定的,每年平均下來一天的時間,現在來看,也是不一樣長的。
例如,第 1 年算出來平均一天的時間是 23.9997 小時,第 2 年可能是 23.998 小時,第 3 年可能是 23.999 小時...
那按照 1 秒 = 1 / 86400 天的定義,每一年的「秒」,也是不一樣長的。
這就比較尷尬了,人們以地球自轉爲依據,定義出來的時間,還是不準!
你可能會想,時間有誤差會有什麼問題嗎?人們依賴不準確的天文現象,不也生活了幾個世紀麼?
確實,對於人們的基本生活影響其實並不大。但隨着人類活動的發展,人們對於高精度的時間場景開始變得越來越多。
例如,體育賽事中百分之一秒的差距就能決定勝負,炮彈的發射要精確在千分之一秒內發生,雷達技術甚至需要精確到百萬分之一秒...
尤其是衛星發射、火箭試驗等航天領域,對高精度的時間系統也提出了越來越高的要求!
怎麼辦?怎麼徹底解決時間不準的問題?
聰明的科學家們開始思考,既然觀測天文現象無法解決這個問題,那在微觀層面能否找到比較好的解決方案嗎?
這時,他們開始把目光投向了「微觀世界」。
一秒到底有多長?
讓我們梳理一下我們的需求。
一直以來,我們對於「秒」的定義需求,從本質上講,就是想要一個「完全穩定」的週期,也就是說,期望每一秒都是固定「等長」的。
而以天文觀測、地球自轉爲基礎的時間測量,做不到這一點。
那在微觀世界層面,是否存在一種元素,它的運動週期是「高度穩定」,不受外界環境影響的呢?
科學家們沿着這個思路開始探索...
好,現在讓我們把視角下放,來到原子世界。
一個原子雖然很小,但它內部卻是一個很複雜的世界。
每個原子都有一個原子核,核外分層排布着高速運轉的電子,當原子受電磁輻射時,它的軌道電子可以從一個位置「跳」到另一個位置,物理學上稱此爲「躍遷」。
人們發現,原子內的電子發生躍遷時,原子會吸收或放出一定能量的「電磁波」,這類電磁波就是一種「週期運動」,我們也可以把它看成原子內部的「振盪」。
基於這個原理,科學家們開始不斷地試驗、研究,嘗試尋找一種運動「週期短、高度穩定」的原子。
終於,科學家們發現確實存在這樣一種原子:銫原子,它內部的振盪週期比其它原子都要更短、更穩定,而且,這個過程基本不受環境因素的干擾。
經過層層試驗,科學家們認爲這是目前人類在地球上可測量到的,運動週期最短、週期最穩定的元素!
之後,科學家們就以之前定義的「秒」爲基礎,去測量一秒內這個銫原子內部電子週期運動的「次數」,測量出來的結果爲 9192631770 次(91 億 + 次)。
基於此,科學家們決定「拋棄」原來基於天文測量的秒,重新定義「秒」的時長,就是這個高度穩定的運動週期。
因此,在 1967 年,國際度量衡大會決定採用,以銫原子躍遷 9192631770 個週期,所持續的時間長度定義爲 1 秒!
注:這個測量原理和測量過程比較複雜,這裏把這些物理細節簡化了。不用太過糾結這個數值是怎麼測量出來的,你只需要理解,這個微觀原子內部的振盪週期是非常穩定的,它比之前根據天文現象測量出來的秒,要精確多得多。
而基於這個銫原子振盪製造出來的時鐘,我們就把它稱之爲「原子鐘」。
有了原子鐘,這就意味着,原子鐘輸出的每一秒,都是絕對「等長」的,非常穩定,這樣一來,就實現了「精準計時」!
這個精確程度可以達到多高呢?
2000 萬年不差 1 秒!可見其精準程度之高。
科研技術還在發展,精密設備和測量能力也越來越高,最新的原子鐘甚至可以達到 1 億年不差 1 秒!
有了原子鐘,人們基於原子鐘又確立了一套新的時間標準,叫做「國際原子時」(International Atomic Time,簡稱 TAI)。
科學家們規定,從 1958-01-01 00:00:00 起,用原子時開始計時,它每走的一秒,都是非常精確的一秒(固定等長),實打實的一秒,完全穩定的一秒。
這個方案非常棒,至此終於解決了秒不固定長的問題。
那有了這個國際原子時,可否讓它直接取代掉前面說的——以天文現象計時的「世界時」呢?
答案是否定的,這個問題遠比想象的複雜得多,這是爲什麼呢?
世界標準時間是怎麼來的?
現在,科學家制定出了兩套時間標準:
-
世界時:基於天文現象 + 鐘錶計時,永遠與地球自轉時間相匹配
-
國際原子時:基於原子鐘計時,每一秒的週期完全等長且固定
假設我們以國際原子時爲時間標準,那會發生什麼現象呢?
因爲原子時非常穩定,但世界時隨着地球自轉變慢,會越來越慢,就會發生這種現象:
-
原子時走得快,世界時走得慢,時間越久,兩者差距越來越大
-
日復一日,幾百年後,世界時的正午 12 點是太陽高照的時刻,而原子時可能已經走到了下午 2 點了
-
幾千年後,太陽高照的時刻,原子時可能已經走到了晚上 8 點!
晚上 8 點是太陽高照的時刻,你能想象這種情況嗎?
這太顛覆我們的生活認知了...
基於天文測算的世界時,已經指導我們人類生活了上千年,人類早已習慣了這種時間標準,直接被原子時取代,肯定是不能接受的。
但我們又需要原子時這種高度穩定的計時標準,來發展科學研究,兩者發生矛盾,這怎麼辦?
科學家們又開始思考,終於想到一個互相兼容的解決方案。
既然兩套時間標準都很重要,那兩者都保留,不會互相取代。
我們可以再建立一套「新的時間標準」,這套時間以「原子時爲基準」,開始計時,走的每一秒都是穩定、精確的。
同時,爲了兼顧基於天文測量的世界時,人類會「持續觀測」世界時與這個新時鐘的差距。
如果發現兩者相差過大時,我們就「人爲」地調整一下這個時鐘(加一秒或減一秒),讓兩者相差不超過 0.9 秒。
例如,這個時鐘本身比世界時走得快,經過一段時間後,如果發現兩者相差越來越大,那就給這個時鐘「加一秒」,讓這個時鐘在 23:59:59 的下一秒變爲 23:59:60 秒,讓它與世界時差距控制在 0.9 秒以內,這個操作過程,相當於讓快的時鐘稍微「等」一下走得慢的世界時。
而加的這一秒,科學家把它定義爲「閏秒」。
是不是挺有意思?聽說過閏年,沒想到還有閏秒!
當然,當地球自轉速度變快時,這裏也有可能是減一秒,即從 23:59:58 直接跳到 00:00:00。但這種情況比較少,大部分情況下,地球自轉速度是越來越慢的。
這麼做的好處在於,這個時鐘的每一秒的計時依舊是精確的,而且還兼顧了日常生活使用的世界時,一舉兩得!
由於這個時鐘是基於原子時 + 世界時「協調」得出的,所以科學家們把它定義爲協調世界時(Coordinated Universal Time,簡稱 UTC)。
看到了麼?我們在開發時經常看到的 UTC,原來是這樣來的!
有了這個研究成果,有技術能力的國家都紛紛製造自己的原子鐘,然後計算協調世界時。
同時,爲了進一步降低原子鐘的測量誤差,每個國家會在每個月,統一上報自己計算的世界協調時到一個權威機構,然後這個權威機構會根據各國實驗室的精度,進行加權計算,算出「最終」的協調世界時。
之後,再把這個最終的時間下發到各個國家,讓各個國家進行「對錶」校準,保證全世界的時間誤差在 100 納秒以內。
至此,科學家們建立的這套時間標準,就是我們現在沿用至今的「標 準 時 間」!
值得一提的是,配合計算世界協調時的國家,也有中國,這個實驗室就是「中國科學院國家授時中心」,它位於中國的陝西省渭南市蒲城縣,持續維護中國的標準時間。
爲什麼國家授時中心會設立在陝西省?因爲陝西省的地理位置處於中國的中部,從這個位置向各地廣播時間時,對全國每個地區距離都是相對平均的。
之後,中國會在自己算出的世界協調時的基礎上,再加 8 個小時(中國在東八區),最終得出來的時間,就是「北 京 時 間」!
沒錯,就是我們經常在新聞播報上聽到的,北京時間。
是不是挺有意思?北京時間並不是在北京產生的,而是在陝西省,並與參與世界時間的制定和校準。
至此,全新的世界標準時間確立了,這套時間標準於 1972 年正式確定,一致沿用至今。
有了標準時間,那麼接下來的問題就是,這個標準時間到底是如何同步到我們的電腦、手機、電子設備上的呢?
這就是下面要講的「授時」。
計算機如何同步時間?
到現在我們知道,世界標準時間和北京時間是怎麼來的,但北京時間的產生是在陝西省,難道校準一次時間需要跑到這裏嗎?
很顯然是不需要的。
位於陝西省的中國科學院國家授時中心,產生北京時間後,會通過一系列方式,把這個時間廣播出去,這個過程,就叫做「授時」。
具體怎麼做呢?
國家授時中心提供很多授時方式,例如無線電波、網絡、電話,都可以把時間廣播出去。
通常來說,無線電波的傳播速度更快、傳播誤差小,所以授時中心會通過這種方式,把時間發送給全國各地的「時間服務器」。
時間服務器有了準確的時間後,再通過其它方式(例如網絡)廣播到下一層的終端用戶使用。
經過這麼一番研究,到這裏我們就可以解釋文章開頭的問題了。
一個時間服務器,原來是通過國家授時中心同步時間,然後再給其它終端提供時間同步服務的。
那我們的計算機如何和它保持同步呢?
你可能會想,最簡單的方式就是,客戶端向服務端「請求獲取」標準時間,服務端響應時間數據,客戶端修改自己的「本機時間」即可。
但事情沒你想的這麼簡單。
因爲數據在網絡傳輸過程中,也是需要時間的,這個時間也會影響到時間的準確性。
這怎麼辦呢?
於是人們想了一種方案,當計算機在做時間校準時,也需要把網絡延遲計算進去,最後「修正」這個同步過來的時間,降低誤差。
現在,已經有個軟件已經把這一切都做好了,如果你瞭解一些運維相關的工作,就會知道,我們部署應用程序的服務器上,都會啓動一個「自動校準」時間的服務,這個服務就是 NTP(Network Time Protocol),它可以保證每臺機器的時間與時間服務器保持同步。
那 NTP 是怎麼同步服務器時間的呢?
這裏就涉及到 2 個重點:
-
NTP 如何同步時間?
-
同步時間時,對正在運行的程序有沒有影響?
先來看第一個問題:NTP 如何同步時間?
簡單來講,它是通過在網絡報文上打「時間戳」的方式,然後配合計算網絡延遲,從而修正本機的時間。
根據圖示可以計算出網絡「傳輸延遲」,以及客戶端與服務端的「時間差」:
-
網絡延時 = (t4 - t1) - (t3 - t2)
-
時間差 = t2 - t1 - 網絡延時 / 2 = ((t2 - t1) + (t3 - t4)) / 2
這個計算過程假設網絡來回路徑是對稱的,並且時延相同。
這樣一來,客戶端就可以「校準」自己的本機時間了,與服務端保持同步,這個時間誤差在廣域網下是 10ms - 500ms,在局域網下通常可以小於 1ms。
再來看第二個問題:同步時間時,對正在運行的程序有沒有影響?
例如,我們很多時候寫的程序代碼是這樣的:
t1 = time.now()
// 時間發生校準
t2 = time.now()
// t2比t1小怎麼辦?
elapsed = t2 - t1
t2 的時間真的會比 t1 小嗎?
這裏就牽涉出 2 個概念:牆上時鐘、單調時鐘,它們之間有什麼區別呢?
-
牆上時鐘:通常就是指前面講到的世界協調時 UTC,校準時間後,可能發生回撥
-
單調時鐘:計算機自啓動以後經歷的納秒數,不會回撥
一般我們寫的代碼,像上面程序調用的「時間 API」,通常獲取的時間是牆上時鐘,所以,如果時間發生校準,就可能會發生「時光倒流」的情況。
這必然對程序產生很大的影響,怎麼解決這個問題呢?
幸運的是,NTP 在校準時間時,提供了 2 種方式:
-
ntpdate:一切以服務端時間爲準,「強制修改」本機時間
-
ntpd:採用「潤物細無聲」的方式修改本機時間,把時間差均攤到每次小的調整上
也就是說,ntpd 當接收到需要「回撥」的時間時,會讓本機時間走得「慢」一點,小步調整,逐漸與服務端的時鐘「對齊」,這樣一來,本機時間依舊是遞增的,避免發生「倒流」。
當我們在配置 ntp 服務時,需要格外注意這種情況。另外,在編寫程序時,也要注意調用的時間 API 獲取的是哪個時間,避免業務邏輯發生異常。
至此,我們從看似簡單的時間問題,一步步深挖到時間的定義,再到時間是如何同步到計算機和終端設備的,怎麼樣,有沒有解答了你心中的很多疑惑?
總結
好了,總結一下。
這篇文章我們講了非常多的概念,這裏我們再重新梳理一遍。
1、人類的早期生活,依靠觀測「天文現象」來測量時間,基於地球自轉規律,定義了一套時間標準:「世界時」。
2、後來人們發現,由於地球公轉軌道是一個橢圓,並且地球自轉還受到地球內部的影響,自轉速度越來越慢,人們發現世界時測算出的時間「不準」。
3、科學家們開始從「微觀世界」尋找更穩定的週期運動,最終確定以「銫原子」的振動頻率爲基準,製造出了「原子鐘」,確立了「世界原子時」,並重新定義了「秒」長度,時長高度精確。
4、但由於人類社會活動已高度依賴「世界時」,所以科學家們基於「原子時」和「世界時」,最終確立出新的時間標準:「世界協調時」,把它定義成了全球的時間標準,至此,世界標準時間誕生。
5、中國基於「世界協調時」再加上 8 小時時區之差,確立了「北京時間」,並廣播給整個中國大地使用。
6、「國家授時中心」把北京時間廣播給全國的「時間服務器」,我們生活中使用的時間,例如計算機,就是通過時間服務器自動同步校準的。
7、計算機通過 NTP 完成和時間服務器的「自動校準」,我們的應用程序基於此,才得以獲取到準確的時間。
8、NTP 服務應該採用潤物細無聲的方式同步時間,避免時間發生「倒流」。
後記
這篇文章是我有史以來,最難寫的一篇,因爲其中有大量科普類知識,涉及範圍之廣遠超我的想象。
在寫這篇文章時,我至少閱讀了 30 篇以上的資料,很多時候會因爲一個很小的細節,又深挖出更多相關的領域的知識,讓我目不暇接。
例如,銫原子的振動頻率是怎麼測量的?爲什麼能測量得這麼精確?各個國家的原子鐘爲什麼會有差異?計算機是如何處理閏秒的?時區是怎麼來的?本初子午線是什麼?...
很多細節我其實並沒有展開來講,我已盡力避開講那些晦澀難懂的物理知識,只保留了重要的理論概念,希望你理解了這其中的原理。如果有些細節你沒有讀懂,可以先嚐試多讀幾遍,也可以與我進一步交流。
同時,在查閱資料過程中,真切地感嘆人類研究成果之偉大,能把時間的誤差,縮小到幾億年的精度,敬佩之情無以言表。
我們在寫代碼時,看似調用了一個簡單的時間 API,可曾想過,背後卻是人類多少年來的智慧結晶。希望這篇文章能解答你對時間的種種疑惑。
如果你對時間這個話題的學習意猶未盡,還可以在我的公衆號後臺回覆「時間」,獲取更多我整理的資料學習。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/SVokpTtlQDUYAo6oc_PGyA