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