餘晟:讓自家系統癱瘓,這事我也幹過

餘晟發表於2015-05-30

文/餘晟

最近幾天國內網際網路圈接連出現停服事故,先是支付寶停服超過 2 小時,然後是攜程停服超過 8 小時。一時間許多人大驚:原來大玩家們的運維水平這麼出乎意料。

我想說的是,我認識的做技術的,許多人都有把網站(系統)搞癱瘓的經歷。有些聚會上,說不出自己把系統搞崩潰過的經歷,人家都不認為你是“自己人”。還好,我是可以榮列“自己人”隊伍的,下面我要說的就是我的經歷。

2007 年,我當時在“抓蝦網”做後臺開發。網齡老一點的讀者大概會記得這個網站,當時排名第一的中文線上 RSS 閱讀器。如果不理解什麼是“RSS 閱讀”,可以理解為“部落格的朋友圈”:當時還沒有微信,只有部落格,線上 RSS 閱讀就是把你關注各部落格的更新都抓回來,拼成“朋友圈”方便閱讀的工具。

問題出現在一天晚上。有一張資料庫的表裡記錄了當前等待執行的任務,通常來說,裡面的記錄應該不超過 100 條。不幸那天程式出了點問題,到下午 6 點堆積了兩三千條記錄,我一直調到晚上 8 點多才算解決,看著資料量一點點降下去,我放心地回家了。

到 11 點半,洗漱完畢,馬上要上床睡覺了,我想登上伺服器確認問題已經解決。檢查發現,還有不到 200 條記錄。看來問題確實已經解決了,只是看著這個數字確實有些不爽,平時都不到 100 呢。於是我想,不如把表給清空了吧,數字就好看了,反正都是會反覆執行的臨時記錄,也沒什麼影響。

等我輸入清空資料庫表的 truncate 語句之後,稍微感覺有些異樣,怎麼執行了這麼久,平時不用 1 秒的語句,現在竟然執行了 5 秒。再看看監控系統,瞬間大驚失色,瞌睡全無:原來我把最重要的部落格地址列表給清空了,抓取、分析、儲存模組群龍無首,都在空轉。

與 delete from 相比,用 truncate 語句清空,速度很快,但無法通過日誌來恢復;雖然資料庫有熱備,但可以想象,1 秒不到的時間裡,這條錯誤的指令已經傳送到各臺熱備機,所以大家都清空了這張表……

我當時剛剛工作不久,而且一直做後臺開發,從來沒有遇到過這樣程度的線上問題。第一反應就是打電話給領導,於是我撥通了振宇(現任去哪兒網集團執行副總裁&無線事業群 CEO)的電話。振宇聽完我的描述,只平靜地說:趕緊恢復資料,最遲明天早上必須要解決,不要讓使用者感覺到。

我本來是想讓他告訴我怎麼處理,結果他只給了我一個目標。後臺系統平時都是我在維護,找其它同事也幫不上忙。所以我雖然滿頭大汗,也只能努力靜下心來,想想到底要怎麼辦。

首先我把相關的模組都停下來,避免弄得自己心煩意亂。然後把資料庫的表都畫在紙上,看看互相之間的關聯,能不能拼一份資料出來。很快我找到了從幾張表拼出原始資料的方案(這時候才知道冗餘設計是多麼好)。寫了一個 Python 指令碼測試,通過。那麼趕緊上線!這時候是凌晨 1 點。

然而事情並沒有那麼簡單,資料倒是恢復出來了,速度慢得嚇人。一共有五百多萬條資料要恢復,每秒鐘只能恢復不到 50 條資料,全部恢復要超過 1 天,肯定會嚴重影響客戶體驗的。

雖然已經接近 2 點了,但我睡意全無(也不敢有)又束手無策。只能一邊徒勞地看著恢復進度,一邊分析:如果沒有冷備(當時確實沒有),看來全部恢復是得 1 天了。怎麼能不讓使用者發現呢?出個維護通告?……忽然我想到,既然使用者訂閱數都在,先把活躍使用者訂閱的、訂閱數量多的部落格地址挑出來,然後再恢復其它的。

很快我統計出符合條件的記錄,大概六十萬條,按照每秒 50 條的速度,一小時可以恢復 18 萬條,4 小時左右可以全部恢復完畢。現在不到 3 點,全部恢復完畢是早上 7 點左右,使用者的第一個活躍期在早上 8 點多(當時絕大多數人都是 PC 上網),應該來得及。

再寫程式,測試,通過,再上線,觀察了一段時間,發現速度是正常的,符合預期。這時候已經四點多,全身溼透了。我給振宇發了個簡訊說“已經在恢復了,確保不會影響客戶體驗”,才倒下去睡覺……

天亮了,起床第一件事就是檢查恢復程式,發現沒有問題。然後我懷著忐忑的心情,裝做沒事人一樣去上班,果然沒有人發現問題。中午吃飯的時候我偷偷找到運維的同事,說了這件事情。他的反應更讓我出乎意料:這有啥,大家都有采坑的時候,我以前在百度,迷糊了把幾個T的前端快取刪掉了,出去抽顆煙,回來該怎麼樣還怎麼樣……

到當天下午,沒有人訂閱的資料也已經恢復了,整個過程還算成功,沒有使用者發現異樣。

後記

這次事件給我的印象太深刻了,尤其是大半夜驚心動魄地除錯,說折陽壽真是不誇張。所以在這之後,我把冷備做起來了,把備份恢復方案做起來了,把資料庫分賬號控制做起來了,再也不敢隨便清空資料表了……吃一塹長一智,好的系統都是一個個小坑填出來的,重要的是看到小坑就要去甜,不能永遠靠人力處理,靠手工搏鬥。長期來看,我改變了工作習慣,每次接手生產系統,第一時間會去關注系統的完整和安全,不再著迷於系統架構和程式碼質量。

現在再回想,還有兩點慶幸:一是抓蝦是面對中文使用者的服務,後來面對要支援多國協作的系統時,才真正知道“全球化”意味著什麼;二是振宇當時只設定了目標,給了我鍛鍊和成長的機會(後來和新浪談技術合作,他給我發的簡訊只有一句話“今天一定要把新浪的人搞定”,我印象也很深刻)。

當然,對我來說,最重要的收穫是一條終身受用的道理:哪怕情況再緊急,也不能手足無措,靜下來心來仔細分析,這才是解決問題的根本途徑。有經驗和沒有經驗的差別,很多時候不在專業技術上,而在於把握能力上。

相關文章