發佈會上已經展示了光鮮亮麗的性能資料,
這裡我嘗試從另外一個角度來說下這一路走下來的痛並快樂著的艱辛歷程,
說下團隊在鐵棒磨針過程中的若干細節。
舞動的橋
1940年11月7日, 竣工才4個月的塔科馬海峽大橋在微風中大幅度舞動, 橋上的汽車急速滑動, 很快就戲劇性的垮塌。 這件事故給建築工程行業造成極大的震驚, 很違反直覺, 很低的風速居然會吹垮一座鋼鐵建造的大橋, 在此之前所有的橋樑專家都沒有意識到這個問題, 事實上若干年後 橋樑結構學與空氣動力學得到極大發展,
其實存儲是一個高危行業, 首先要保障的是不錯, 不丟, 可訪問, 只有在這個前提下, 極致的性能才有意義。 不錯, 不丟, 可訪問, 看起來平淡無奇, 但實踐下來常有如履薄冰之感,
E2E的資料校驗
磁片可能出錯, 記憶體也會出現出現bit反轉, 內核和應用程式更可能出錯, 甚至我們遇到過某廠的一塊CPU在做某些特定運算時就會出錯, 在這樣一堆不可靠的軟硬體環境下, 要構建出一個穩定可靠的存儲平臺(沒有哪個使用者能接受哪怕一個bit的錯誤),
有E2E的資料校驗是否就安全了呢?呵呵坑深不見底,硬體行業的人知道磁片極小的概率發生靜默錯誤(讀出來的資料是錯誤的,但底層介面不報錯,磁片本身也不報錯),如果三份拷貝很長時間都未被讀取,而在這個較長的時間視窗內,如果有三份拷貝所在的3塊盤都發生了靜默錯誤,使用者讀取資料時,存儲系統就會發現3份CRC校驗都不通過,儘管知道出差錯了,卻沒有任何辦法修復。為了降低這種情況發生的概率,我們會定期掃描冷資料,校驗其CRC。
壓縮檢驗
一天新來的同事問大家:“我們在做壓縮的時候,為啥壓縮完後,立刻又解壓縮一次,並且將解壓資料和原始資料再去比對一次?直接壓縮不就完了嗎?”,眾人笑而不語,他思考良久,也未能找到足夠的理由。團隊內老司機告訴他,壓縮本身是一個很複雜的東西,有些庫是協力廠商提供的,儘管我們會review代碼,有嚴格的引入測試,但沒人能保障其絕對正確,萬一壓縮出來的內容是錯的怎麼辦?CPU也可能存在一些偶發性的錯誤,如果壓縮時發生這類小概率的偶發性錯誤,該怎麼辦呢?但戶資料是絕對不能錯的,所以我們這裡採取防禦性程式設計,壓縮完後立即解壓,再和原始內容比對,確保資料不錯。
PAXOS
說到分散式存儲,很多人就言必稱PAXOS,RAFT,PAXOS儼然就成了救世主。PAXOS, RAFT 的確是好東西,但並不是所有的場景都適用。在一個分散式系統中,大家會認為在一個較小的時間視窗內同時發生2台機器failover是一個小概率事件,但隨著集群規模的擴大,集群數量的增多,最終小概率事件長期積累,就變成必然事件了,在quorum=3的時候,PAXOS 協議是無法處理double fail的,甚至無法自愈,需要緊急人為干預才能恢復。想想半夜收到告警,你能在幾分鐘能處理好用戶的IO HANG? 適合的才是最好的,實踐是檢驗真理的唯一標準。
磁片錯誤
對於做存儲的人來說,磁片故障是司空見慣的事情了,本身有一套成熟的處理機制。但百密一疏,我們還是在這上面栽過跟頭,進程主動檢測到binary所在的系統磁片故障,老司機當然知道此時不能再在該盤上發起任何IO 操作,日誌寫入到記憶體中,調用exit, 安靜的退出,不帶走一片雲彩即可。但進程居然無法退出,調用exit 無法退出!而此時其它執行緒還在繼續工作,在幹壞事。所有人都覺得匪夷所思,為啥主執行緒調用 exit, 進程未能退出,其他執行緒在長達幾分鐘內還在繼續幹壞事?團隊大牛反復推演,不放過任何一個蛛絲馬跡,終於搞明白了,原來磁片故障後,exit這段代碼本身並不在記憶體中,調用時會產生major fault, 中斷處理常式會嘗試從磁片上load相應的程式碼片段,而磁片已經故障了,load 被hang住,導致出現前面這些匪夷所思的怪事。
今天雲計算已經成為互聯網的基礎設施,隨著眾多電力,水務,醫療企業上雲,我們又成了這些基礎設施的基礎設施,任何一個黑天鵝都有可能帶來難以估量的影響。只有對這個未知的世界保持敬畏,保持謙卑,才能走得更遠。
由於我們的CRC和資料是邏輯空間上是相鄰的,會不會是這片資料其實不屬於當前檔,而是和另外一個檔搞串了?大膽假設,小心求證,全盤掃描後果然證實了猜想,A,B 兩個檔中間有一部分內容寫串了,詳細調查後確認是EXT4 檔案系統的BUG,它在做空間管理的時候出錯,導致A檔的一個資料片寫入到檔B, 檔B中有一個資料片寫入到檔A中,由於寫入的流程一致,CRC又和資料放置在一起,導致CRC無法發現這個問題,確認問題後解決起來就很簡單了,要麼將CRC和資料分開放置,要麼在計算CRC的時候加上檔的一個特徵值。有E2E的資料校驗是否就安全了呢?呵呵坑深不見底,硬體行業的人知道磁片極小的概率發生靜默錯誤(讀出來的資料是錯誤的,但底層介面不報錯,磁片本身也不報錯),如果三份拷貝很長時間都未被讀取,而在這個較長的時間視窗內,如果有三份拷貝所在的3塊盤都發生了靜默錯誤,使用者讀取資料時,存儲系統就會發現3份CRC校驗都不通過,儘管知道出差錯了,卻沒有任何辦法修復。為了降低這種情況發生的概率,我們會定期掃描冷資料,校驗其CRC。
壓縮檢驗
一天新來的同事問大家:“我們在做壓縮的時候,為啥壓縮完後,立刻又解壓縮一次,並且將解壓資料和原始資料再去比對一次?直接壓縮不就完了嗎?”,眾人笑而不語,他思考良久,也未能找到足夠的理由。團隊內老司機告訴他,壓縮本身是一個很複雜的東西,有些庫是協力廠商提供的,儘管我們會review代碼,有嚴格的引入測試,但沒人能保障其絕對正確,萬一壓縮出來的內容是錯的怎麼辦?CPU也可能存在一些偶發性的錯誤,如果壓縮時發生這類小概率的偶發性錯誤,該怎麼辦呢?但戶資料是絕對不能錯的,所以我們這裡採取防禦性程式設計,壓縮完後立即解壓,再和原始內容比對,確保資料不錯。
PAXOS
說到分散式存儲,很多人就言必稱PAXOS,RAFT,PAXOS儼然就成了救世主。PAXOS, RAFT 的確是好東西,但並不是所有的場景都適用。在一個分散式系統中,大家會認為在一個較小的時間視窗內同時發生2台機器failover是一個小概率事件,但隨著集群規模的擴大,集群數量的增多,最終小概率事件長期積累,就變成必然事件了,在quorum=3的時候,PAXOS 協議是無法處理double fail的,甚至無法自愈,需要緊急人為干預才能恢復。想想半夜收到告警,你能在幾分鐘能處理好用戶的IO HANG? 適合的才是最好的,實踐是檢驗真理的唯一標準。
磁片錯誤
對於做存儲的人來說,磁片故障是司空見慣的事情了,本身有一套成熟的處理機制。但百密一疏,我們還是在這上面栽過跟頭,進程主動檢測到binary所在的系統磁片故障,老司機當然知道此時不能再在該盤上發起任何IO 操作,日誌寫入到記憶體中,調用exit, 安靜的退出,不帶走一片雲彩即可。但進程居然無法退出,調用exit 無法退出!而此時其它執行緒還在繼續工作,在幹壞事。所有人都覺得匪夷所思,為啥主執行緒調用 exit, 進程未能退出,其他執行緒在長達幾分鐘內還在繼續幹壞事?團隊大牛反復推演,不放過任何一個蛛絲馬跡,終於搞明白了,原來磁片故障後,exit這段代碼本身並不在記憶體中,調用時會產生major fault, 中斷處理常式會嘗試從磁片上load相應的程式碼片段,而磁片已經故障了,load 被hang住,導致出現前面這些匪夷所思的怪事。
今天雲計算已經成為互聯網的基礎設施,隨著眾多電力,水務,醫療企業上雲,我們又成了這些基礎設施的基礎設施,任何一個黑天鵝都有可能帶來難以估量的影響。只有對這個未知的世界保持敬畏,保持謙卑,才能走得更遠。