![]()
本文來(lái)自微信公眾號(hào): 宇眾不同的露萱 ,作者:宇眾不同的露萱,原文標(biāo)題:《為什么 Google 要重新定義一秒鐘?》
在寫(xiě)代碼的時(shí)候,我們習(xí)慣了調(diào)用System.currentTimeMillis(),默認(rèn)拿到的就是一個(gè)平滑、單調(diào)、絕對(duì)向前的數(shù)字。這種感覺(jué)就像我們呼吸空氣一樣自然——時(shí)間嘛,不就是一直在往前走嗎?
直到線上第一次碰到因?yàn)闀r(shí)間回?fù)軐?dǎo)致的分布式ID重復(fù)事故,我才被現(xiàn)實(shí)狠狠補(bǔ)了一課。
后來(lái)我去翻Google關(guān)于TrueTime和Leap Second(閏秒)的工程文檔,心里最大的感觸不是“這套方案有多牛”,而是一種極其荒謬的落差:
我們今天支撐著整個(gè)現(xiàn)代文明的計(jì)算機(jī)網(wǎng)絡(luò),底層居然建立在一個(gè)連“一秒鐘有多長(zhǎng)”都說(shuō)不清楚的脆弱基石上。
為了不讓這個(gè)基石崩塌,Google干脆做了一件聽(tīng)起來(lái)有點(diǎn)霸道的事情:他們單方面決定,在某些日子里,重新定義軟件世界里的“一秒鐘”。
很多關(guān)于閏秒的文章,一上來(lái)就喜歡從地球自轉(zhuǎn)減慢、潮汐摩擦開(kāi)始講起。
這些天文知識(shí)當(dāng)然沒(méi)錯(cuò),但天文學(xué)家的煩惱,原本是不需要軟件工程師來(lái)買(mǎi)單的。
天文學(xué)家的時(shí)間叫UT1,是以地球自轉(zhuǎn)為基準(zhǔn)的——地球轉(zhuǎn)一圈就是一天,平分給86400秒。但現(xiàn)實(shí)是,地球這個(gè)大石頭一點(diǎn)都不規(guī)整,內(nèi)部巖漿在涌動(dòng),表面海水在摩擦,甚至連板塊地震都會(huì)改變它的轉(zhuǎn)速。所以,物理世界里的“一天”,從來(lái)都不是精準(zhǔn)的86400秒。
而計(jì)算機(jī)科學(xué)家用的是原子鐘(TAI),靠銫原子振蕩來(lái)計(jì)數(shù)。原子鐘極度精準(zhǔn),它不在乎地球怎么轉(zhuǎn),它的秒是絕對(duì)均勻的。
這兩撥人湊在一起,矛盾就出來(lái)了。
天文學(xué)家說(shuō):“太陽(yáng)升到最高點(diǎn)必須是中午12點(diǎn),你原子鐘走得太快,和地球自轉(zhuǎn)偏了,你得等等我。”計(jì)算機(jī)派說(shuō):“我的邏輯只要求絕對(duì)單調(diào),你一會(huì)兒走得快一會(huì)兒走得慢,我的系統(tǒng)怎么算高并發(fā)事務(wù)?”
最后在1972年,大家搞了個(gè)折中方案,叫協(xié)調(diào)世界時(shí)(UTC)。規(guī)則很粗暴:以原子鐘為準(zhǔn),但如果和地球自轉(zhuǎn)偏差快超過(guò)0.9秒了,就在某個(gè)月的最后一天,強(qiáng)行插進(jìn)1秒。
這就是那個(gè)著名的23:59:60。
第一次讀到這里的時(shí)候,我其實(shí)覺(jué)得挺神奇的——時(shí)間居然能出現(xiàn)60秒。但如果你寫(xiě)過(guò)基礎(chǔ)庫(kù)或者內(nèi)核代碼,你就會(huì)明白,這對(duì)于計(jì)算機(jī)來(lái)說(shuō)根本不是神奇,這是一個(gè)噩夢(mèng)。
計(jì)算機(jī)的最大愿望,其實(shí)就是大家都別改時(shí)間。
在軟件工程師構(gòu)筑的世界里,有一個(gè)至高無(wú)上的基本假設(shè):時(shí)間是單調(diào)遞增的,且一秒就是一秒。
你可以想想看,POSIX時(shí)間戳(Unix Timestamp)的底層定義就是“從1970年1月1日開(kāi)始流逝的秒數(shù)”。整個(gè)軟件生態(tài)——從Linux內(nèi)核的定時(shí)器、線程鎖,到數(shù)據(jù)庫(kù)的MVCC事務(wù)版本號(hào)、分布式系統(tǒng)的Lease租約——全部建立在這個(gè)假設(shè)之上。
但23:59:60的出現(xiàn),直接把這個(gè)基本假設(shè)砸碎了。
當(dāng)國(guó)際地球自轉(zhuǎn)服務(wù)(IERS)宣布要加一秒的時(shí)候,底層操作系統(tǒng)面臨著一個(gè)極其尷尬的選擇:
讓時(shí)間出現(xiàn)23:59:60:大多數(shù)編程語(yǔ)言的標(biāo)準(zhǔn)庫(kù)和POSIX API根本沒(méi)有定義過(guò)第60秒。你調(diào)用時(shí)間函數(shù)返回這個(gè)值,很多解析代碼直接報(bào)錯(cuò)崩掉。
讓時(shí)間停頓一秒(把時(shí)鐘凍結(jié)在59秒兩次):表面上看沒(méi)有非法數(shù)字了,但對(duì)于高并發(fā)系統(tǒng)來(lái)說(shuō),意味著在這一秒內(nèi),兩個(gè)不同時(shí)刻產(chǎn)生的日志記錄,擁有完全相同的時(shí)間戳;兩個(gè)請(qǐng)求發(fā)起的死鎖檢測(cè),時(shí)間差是0。
把時(shí)間往回?fù)芤幻耄哼@是最慘的。時(shí)鐘倒退,直接擊穿了大部分基于邏輯時(shí)鐘和分布式鎖的算法。
2012年那次著名的“閏秒大慘案”,本質(zhì)上就是Linux內(nèi)核在處理NTP傳過(guò)來(lái)的閏秒標(biāo)志位時(shí),觸發(fā)了一個(gè)隱藏在futex(快速用戶空間互斥鎖)里的死鎖Bug。當(dāng)時(shí)Reddit、Mozilla、Qantas航空的系統(tǒng)成片崩潰,服務(wù)器CPU瞬間飆到100%。
那次事故給整個(gè)工程界留下的心理陰影極其深遠(yuǎn)。
大家突然發(fā)現(xiàn),天文學(xué)家為了讓自轉(zhuǎn)和太陽(yáng)對(duì)齊而做出的“文明浪漫”,對(duì)于高并發(fā)的數(shù)字世界來(lái)說(shuō),無(wú)異于一次高空投彈。
真正的瓶頸不在于怎么寫(xiě)那幾行代碼去兼容23:59:60。
真正的瓶頸在于,在復(fù)雜的分布式系統(tǒng)中,你根本無(wú)法保證幾萬(wàn)臺(tái)服務(wù)器能在絕對(duì)相同的微秒級(jí)時(shí)間內(nèi),同時(shí)收到并執(zhí)行“加一秒”的指令。
哪怕只有幾毫秒的時(shí)間差,集群內(nèi)某些節(jié)點(diǎn)進(jìn)入了第60秒,另一些節(jié)點(diǎn)還在第59秒,分布式數(shù)據(jù)庫(kù)的一致性就蕩然無(wú)存了。
既然物理世界不可預(yù)測(cè),而多節(jié)點(diǎn)同步又不可能完美,Google的工程師們?cè)?008年前后做出了一個(gè)非常符合他們實(shí)用主義風(fēng)格的決定:
我不陪天文學(xué)家玩了。我也不在軟件里處理什么23:59:60了。從今天起,我的服務(wù)器里根本不存在這一秒。
這就是所謂的Time Smear(時(shí)間抹平/時(shí)間漸變)。
Google的做法說(shuō)白了有點(diǎn)“自欺欺人”,但極其管用:
當(dāng)閏秒要來(lái)的那一天,Google的內(nèi)部NTP服務(wù)器不會(huì)向客戶端下發(fā)任何“要加一秒”的警告。相反,它從閏秒發(fā)生前12小時(shí)開(kāi)始,故意把自己的時(shí)鐘擺頻(Clock Frequency)調(diào)慢一點(diǎn)點(diǎn)——每一秒都比真正的物理秒稍微長(zhǎng)那么一丁點(diǎn)。
它把那需要增加的1秒鐘,均勻地拆碎成幾十萬(wàn)份,“抹”進(jìn)了這24小時(shí)(前12小時(shí)到后12小時(shí))的每一個(gè)瞬間里。
等這24小時(shí)過(guò)去,那額外的1秒鐘已經(jīng)在不知不覺(jué)中被系統(tǒng)消化掉了。時(shí)鐘平滑地貼合上了新的UTC時(shí)間,而運(yùn)行在上面的任何業(yè)務(wù)代碼、任何數(shù)據(jù)庫(kù)、任何內(nèi)核鎖,全程毫無(wú)察覺(jué)。
從頭到尾,沒(méi)有任何時(shí)間跳躍,沒(méi)有任何23:59:60,也沒(méi)有任何時(shí)間回?fù)堋?/p>
如果站在純粹的標(biāo)準(zhǔn)制定者或者天文學(xué)家的角度來(lái)看,Google的Time Smear簡(jiǎn)直是“邪教”。
因?yàn)樗谀ㄆ降哪?4小時(shí)里,Google服務(wù)器所輸出的時(shí)間,既不是嚴(yán)格的UTC(因?yàn)闆](méi)有處理60秒),也不是嚴(yán)格的TAI(因?yàn)樗室庾呗耍且粋€(gè)由Google自主定義的、只存在于它數(shù)據(jù)中心內(nèi)部的“偽時(shí)間”。
在標(biāo)準(zhǔn)協(xié)議的衛(wèi)道士看來(lái),這是對(duì)國(guó)際時(shí)間標(biāo)準(zhǔn)的公然篡改。
但現(xiàn)實(shí)卻無(wú)比真實(shí):工業(yè)界最終全盤(pán)接受了這個(gè)代價(jià)。
因?yàn)閷?duì)于軟件系統(tǒng)來(lái)說(shuō),“符合標(biāo)準(zhǔn)”遠(yuǎn)沒(méi)有“系統(tǒng)不崩”來(lái)得重要。
后來(lái)AWS跟進(jìn)了,Meta(當(dāng)時(shí)的Facebook)跟進(jìn)了,微軟也跟進(jìn)了。大家發(fā)現(xiàn),用微小的頻率偏差去換取時(shí)鐘的絕對(duì)單調(diào)和連續(xù),是收益最高、風(fēng)險(xiǎn)最小的工程選擇。
甚至可以說(shuō)是Google的這種強(qiáng)硬姿配,直接倒逼了上層計(jì)量學(xué)界去重新審視閏秒的存在價(jià)值。
在經(jīng)歷了四十多年的折騰之后,2022年第27屆國(guó)際計(jì)量大會(huì)(CGPM)終于通過(guò)了一項(xiàng)歷史性決議:決定在2035年之前,正式取消UTC中的閏秒機(jī)制。
天文學(xué)家們最終向計(jì)算機(jī)科學(xué)家妥協(xié)了。在這個(gè)高度依賴算法和數(shù)據(jù)流轉(zhuǎn)的時(shí)代,文明最終選擇放棄讓機(jī)械的時(shí)間去強(qiáng)行貼合地球的律動(dòng)。
但其實(shí),今天工程界依然留著一個(gè)尷尬的尾巴。
雖然大家都接受了“抹平”的思想,但因?yàn)楫?dāng)年沒(méi)有統(tǒng)一的標(biāo)準(zhǔn),各大云計(jì)算巨頭的Smear策略并不一致:
Google采用的是以閏秒時(shí)刻為中心的24小時(shí)線性抹平;
AWS采用的是從前一天中午開(kāi)始的24小時(shí)余弦/線性抹平;
Meta曾經(jīng)使用過(guò)17.5小時(shí)(63000秒)的抹平方案;
這就導(dǎo)致在有閏秒出現(xiàn)的那一天,如果你的系統(tǒng)跨了云平臺(tái)——比如一部分節(jié)點(diǎn)部署在AWS,另一部分部署在GCP——它們?cè)谀ㄆ狡陂g拿到的時(shí)間戳,最大可能存在幾百毫秒的偏差。
在極其敏感的跨云分布式事務(wù)里,這個(gè)偏差依然有可能引發(fā)意料之外的數(shù)據(jù)不一致。
看似完美的工程妥協(xié),只是把一個(gè)顯性的崩潰Bug,變成了一個(gè)隱蔽的、概率發(fā)生的分布式漂移問(wèn)題。
我們搞了幾萬(wàn)年的時(shí)間計(jì)量,建立了如此龐大的分布式計(jì)算網(wǎng)絡(luò),但直到今天,我們依然無(wú)法完全消除物理世界與數(shù)字世界之間的那道時(shí)間縫隙。
本內(nèi)容由作者授權(quán)發(fā)布,觀點(diǎn)僅代表作者本人,不代表虎嗅立場(chǎng)。如對(duì)本稿件有異議或投訴,請(qǐng)聯(lián)系 tougao@huxiu.com。
本文來(lái)自虎嗅,原文鏈接:https://www.huxiu.com/article/4881845.html?f=wyxwapp
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.