01 穩定性(一)如何應對事故並做好覆盤?

這幾年,我在跨境電商經歷了業務快速發展的黃金時期,也遇到了一些令人“出乎意料”的事故。

最嚴重的一次宕機,直接導致技術組織調整和一位技術大牛的離開,公司也賠了十幾萬;甚至半年後還有銷售經理和我抱怨說:“如果那一天系統不出問題,訂單量肯定會創新高。”

經歷了大小數以百計的事故後,從 82 原則上看,我發現 20% 是因爲人員能力和機制流程的欠缺,80% 則是因爲人員的穩定性意識不足,並且故障應對方法不當。而作爲技術 Leader 的你,如何認識穩定性、如何應對故障、如何從過往的事故中汲取足夠的經驗,就成爲一個團隊能否做好穩定性的關鍵。
怎麼衡量系統穩定性?

一般來講,通過統計系統不可用的時長或次數就可以對穩定性進行量化,比如業內常說 4 個 9 的可用性(即 1 年內 99.99% 的時間系統是可用的,不可用時長僅爲 52.6 分鐘)。

在餓了麼和阿里,每個財年我們會確定穩定性 KPI,以事故數的計量爲準,結合團隊情況和過往結果揹負不同數量的事故指標。事故按照影響程度的不同會劃分爲幾級,不同級別的事故數指標也不同。所以針對穩定性的提高也可以看作圍繞事故的治理,可以從事故發生的前、中、後分階段來看對應的關鍵點。

    事故的類型:可用性事故、資損類事故。

    事故前預防:主動治理減少系統的風險隱患,重點在變更管控、可用性設計、應急預案與演練。

    事故中應急:“止血、恢復”是原則。

    事故後覆盤:目的不是追責,查根因、改進架構、完善應急、總結經驗纔是我們想要的。

這一講,我們來了解一下故障的應急與事故的覆盤(預防治理我會在下面兩講分不同事故類型來詳細講解),因爲事故的發生要結合具體的上下文背景、系統架構、甚至組織結構來看,並非千篇一律。

希望今天的內容能幫你更深刻地理解穩定性的價值,並結合實際工作更加有條不紊地應對線上故障、有價值地進行事故的覆盤總結。
你遇到的事故是什麼類型?

從事故特性上看,我們可以分爲可用性事故和資損類事故。

    可用性事故:技術原因導致系統部分或者全部功能不可用,業務沒辦法正常完成對應流程或者提供對應服務。比如因爲網絡、DB、接口 Bug 等原因,用戶沒辦法登錄、商品列表不顯示等。

    資損類事故: 系統的功能都能正常使用,但因爲邏輯、計算等原因讓業務的某一方產生了資金損失。比如用戶支付一律爲 0 元、錯發 999 無門檻優惠券、商戶清結算少打款給商戶等等。

那麼它們的區別是什麼呢?

可用性事故的根因大多在技術本身,包括但不限於: DB 設計、接口實現、鏈路架構、上下游的依賴、中間件的實現等原因,特點是發現容易、杜絕難、業務影響明顯、對應急處理速度要求高。

而資損類事故更多和隱蔽的業務邏輯和架構設計的缺陷有關,可能還涉及產品邏輯或業務錯配,特點是非常隱蔽、難發現、往往持續時間長、防控成本高、大部分開發同學意識薄弱。

因爲這樣的特性差異,兩類事故在預防治理的思路和方法上有一定區別,但在故障的應急和事故覆盤上,思路相對一致。那麼當故障發生時,你要發揮什麼作用呢?
故障發生時應該如何應急?

事故現場往往伴隨着“混亂”,試想一下,你團隊的小夥伴昨晚剛發佈上線了新系統,今天上午一切正常,下午 App 核心頁面突然無法顯示、客服反饋說大量用戶來電投訴,可誰都說不清楚到底是怎麼回事,十幾分鍾過去了,系統依然沒有恢復,類似的場景你是否經歷過?

那麼這時,你應該起到“定海神針”的作用,故障發生時控場就是你的核心職責。 要有條不紊地安排同學進行排障、確定信息溝通的秩序、結合信息做好線上同步,並參與決策。

在阿里,故障的處理有一個“ 1-5-10 ”的標準,即 1 分鐘發現、5 分鐘響應、10 分鐘恢復。很明顯,故障處理的核心在於“快”,讓業務最快止血、恢復、避免影響進一步擴大。

故障處理的生命週期,可以分爲 4 個階段:發現異常、排查問題、判斷決策、恢復處理。這 4 個階段對應的行動並不是完全串行的,雖然有一定的依賴關係,但在實際的處理過程中應該並行展開。類似 fork/join 的模式,不斷完成小任務、不斷彙總信息,不斷做出判斷與決策,形成循環直到故障恢復。

接下來,我以外賣點餐的業務爲例,講一下故障的發現、排查、決策與恢復都要注意哪些核心要點,因爲故障處理的核心原則相同,所以這些要點在其他業務場景中也適用。(時序圖與真實系統間我做了一些模糊處理,但是不影響案例說明。)

我們要點外賣的話,大體的流程是這樣的:

    用戶打開 App,根據用戶 LBS 顯示餐廳列表,選擇進入某一家餐廳;

    添加菜品到購物車,進入結算頁確定收貨人、優惠紅包、訂單金額,生成訂單;

    跳轉第三方支付,並返回支付結果;

    商家接收訂單推送,操作接單並備貨;

    騎手根據調度取餐,送達用戶,訂單完成。

故障的解決流程
1. 故障發現

用戶來電反饋訂單無法支付、App 無法登錄,研發發現下單 QPS 曲線同比下跌,這些都是事故發生時的現象,雖然現象不完全等於故障點,但通常最早出現異常現象的地方和故障根因關聯最大,所以第一時間發現異常對於鎖定問題至關重要。

故障發現就是系統異常反饋到研發的過程,這裏我畫了一個簡單的腦圖,分類說明故障發現的幾種常見方式:

開發同學往往更關注技術類指標,比如 QPS、CPU LOAD,可 Leader 除此之外應該更多地從業務場景出發,結合需求來看系統的業務監控覆蓋是否完全。業務監控往往更加敏銳,但是要想用好,就需要對業務和系統有較長鏈路的理解和掌握,而這恰恰是技術 Leader 的優勢。

比如用戶進入餐廳後會添加菜品到購物車,並跳轉到結算頁完成下單。菜品服務會提供一個查詢接口,根據餐廳 ID 返回菜品信息。假設這個查詢接口最近做了變更,在庫存邏輯的處理中埋下了一個 Bug,導致實際庫存小於 50 時,庫存的返回值被默認爲 0,而其他數據則一切正常。

那麼此時類似 CPU、內存、I/O 等技術指標可能都不會異常。而因爲是部分實際庫存小於 50 的菜品被影響,用戶依然可以添加其他菜品到購物車,但因爲部分菜品庫存爲 0,用戶想喫卻沒辦法下單,那麼這個時候訂單成交量的環比、同比曲線就有可能下跌,而這個現象會讓我們感知到異常,進而排查問題處理。

總的來說,人工的被動反饋在時間和速度上有較強的不確定性,很容易出現“小故障 * 長時間 = 大事故”的情形。而純粹的技術指標監控又會忽略掉接口正常響應,但是業務異常的場景,只有兩者結合,通過監控告警,最大程度上縮短故障感知的時間,才能早發現早解決,減少業務影響。
2. 故障排查

發現異常,接下來就是排查故障點和故障原因,故障排查最直接有效的核心思路就是直接鎖定 + 排除。

    直接鎖定:最近的變更點與異常現象間有直接的邏輯關聯,進而可以直接鎖定到故障點。比如,剛對下單接口進行了發佈變更,接口的 QPS 曲線就暴跌,可以基本斷定是剛纔的發佈導致。

    排除法:當干擾因素過多(用戶、訂單等幾個系統同時發生變更,引起訂單下跌),很難直接鎖定到故障點,就要結合業務場景,讓整條架構鏈路上的所有關聯方進行自查自證,通過排除法鎖定故障。

這裏你要注意的是,要敢於先懷疑、排查自己的系統,再去考慮上下游關聯方的問題,爲的就是在信息混亂的現場,減少信息的不確定性,以身作則,帶領團隊成員將範圍縮小,針對性地找到問題。

如果你負責的是優惠券相關的系統,在下單的核心路徑上,主要的場景就是優惠券領取、發放、展示、覈銷。你即使不是全部熟悉,也應該與團隊同學共同協同,逐個確認這幾個場景的核心接口是否有異常,通過對應的監控、日誌收集信息並找問題,如果某一處沒有發現問題,就排除並繼續循環。

如果還是沒辦法確定問題,或者只能確定大致範圍,就要充分利用之前的事故經驗了,此時一定要果斷,可以結合情況啓用標準應急手段(比如服務重啓、發佈回滾、非關鍵鏈路降級)。總的來說,在排障的過程中,如果團隊成員都沒有頭緒,你一定要起到主導作用,可以參考我總結的一些要點做好“控場”。

3. 故障決策

既然故障的表現是業務功能有損,那麼在故障決策時爲了讓業務最快止血和恢復,就無法追求完美,一些爲了搶時間的有損決策,就需要 CaseByCase 的人爲處理。

比如平臺要搞一個 517 紅包雨的活動 ,但是紅包系統邏輯錯誤,導致滿 50-10 的紅包發放成滿 10-50,此時已發的紅包要作廢嗎 ?不作廢有大額資損,作廢會導致大量客訴。類似紅包錯配的場景,業務決策非常複雜,能否第一時間止損很大程度上取決於技術 Leader 的現場反應和操作, 要注意故障決策的兩個關鍵點 :

    一定要有明確的決策人、主導者和有效的溝通方式(釘釘羣、多人電話會議、緊急作戰會議室等),讓信息可以通暢地交流出來,並且決策人可以根據情況做判斷與取捨,形成所有人明確的處理結論。 比如,第一時間停止錯誤紅包的發放,確保故障沒有增量,並把決策第一時間同步給團隊成員,並同步相關負責人後續的動作,對已發放的紅包,明確要求負責人彙總各類關鍵信息(紅包數量、涉及金額、涉及用戶數、有效時長、可能資損等)。

    所有的信息一定要數據化,不同的數據量級會導致決策不同,比如紅包錯發 50W 可能只是暫停發放,但是存量紅包依然可以覈銷,損失公司可以承擔。但是如果錯發 5000W,大概就要涉及一系列的調整,這是非常影響決策的。

4. 故障恢復

往往業務決策後就需要執行相應的技術操作,最好的情況當然是在系統設計時就準備了預案,那麼此時可以安全且快速地執行,並且對不涉及業務決策的問題可以技術直接操作,節省時間,比如常見的應急“三板斧”:變更回滾、服務重啓、降級&限流。

而如果沒有預案或情況比較複雜,就涉及線上Fix,比如因代碼不兼容所以無法回滾,或者故障導致髒數據進而影響正常的業務流程推進,又或者紅包金額錯誤需要做數據訂正。你在這個環節要額外注意, 因爲一來這種操作相當於一次“緊急變更”,有可能引入新的風險,二來不同的實現 Fix 成本和用時可能不同,Leader 需要給出自己的判斷。

比如剛剛提到的紅包錯配、錯發的問題,假設影響金額過大,公司決定對存量紅包作廢止損,那麼站在技術角度有很多方法,你需要讓團隊成員明確使用哪種方式:

    下單環節,在“我的優惠券”中通過前端隱藏對應的紅包,讓用戶無法選擇 ;

    根據紅包批次 ID 或者類型,通過腳本刷數,將紅包批量作廢 ;

    在下單接口的校驗環節,增加邏輯判斷,禁止這批紅包覈銷 ;

    通過風控系統攔截使用這類紅包的訂單。

技術 Leader 要考慮不同恢復手段引入的新風險、操作用時、用戶體驗影響的不同,結合當前緊急程度、系統、具體操作人的情況,給出一個技術方面確定的判斷。類似的問題,如果完全沒有預案,我們之前常見的做法還是不動線上系統以免引入新問題,主要通過刷數據解決。

講到這兒,你是不是覺得處理完事故就萬事大吉了呢?並不是,你還要對這次事故做一個全面徹底的覆盤,不讓類似的問題重複發生,那麼覆盤都要注意哪些關鍵點呢?
如何有價值地做事後覆盤?

覆盤的核心不是爲了追責或者甩鍋,而是最大程度榨乾事故的剩餘價值,通過全盤的思考與總結,來看看系統設計、流程機制、應急處理、人員安排等各方面有哪些不足,哪些可以提升的地方,哪些問題是共性的,需要在各團隊進行“大掃除”。

通過一次事故,解決一類問題,讓一個人(團隊)踩過的坑變成所有人踩過的坑,正所謂“一次學費,受益終身”。

你可以從時長、現象、處理時間軸、根因、改進計劃這幾個維度進行復盤, 在以下幾個方面進行深究:

    事故時長:1-5-10 是否達成,如果沒有是爲什麼?哪個環節用時最多,如何提高和改善?

    事故根因:根因不等於直接原因,一個事故的直接原因往往並不複雜,但是根因可能是多個維度的缺失,需要像剝洋蔥一樣一層層找下去。拿庫存接口變更這個Case來說,直接原因就是某段代碼邏輯變更導致,但是應該在測試、發佈、監控、應急影響、預案設計等多個環節展開去看,根因的挖掘並不忌諱“吹毛求疵”。

    事故改進措施:由點推到面、明確到人、明確時間。與根因類似,要結合多個維度形成組合拳的改進點,避免一次性動作,要將重點放在對未來、對同類問題的預防上。核心就是如果再一次發生類似的問題,這些改進措施是不是能起到作用。

關於事後覆盤,你可以這樣理解,我們要深挖事故如何發生的、如何處理的、未來怎麼預防。但要避免情緒化,在覆盤會上的反思、感悟、懊惱沒有任何意義,如何帶領團隊把精力放在改進措施的落實以及事故前的治理上更有價值, 另外,你需要留出時間讓團隊夥伴進行內部的 Review,避免爲了開會而覆盤。
本節小結

雖然你會盡全力保障系統的穩定性,但是按照墨菲定律來說故障又一定會發生,這就形成了一個悖論,即不管你怎麼努力還是會出問題,所以我一直強調:“穩定性是一個先有意識後有能力的事兒”,這一點尤爲重要,畢竟你的態度和認識決定了團隊的重視程度。 這一講我想強調這樣幾個重點:

    毫不誇張地說,系統穩定性對於研發而言一條生死線,這方面做得不好,其他再好也是枉然,因爲穩定性問題“下崗”被優化的 Leader 不在少數。

    對於故障的應急響應,業務的止損與恢復是最重要的,決斷就是要付出一些代價的。

    事故的覆盤不是爲了追責過去,而是爲了在未來避免類似的情況發生。

業務快速發展的同時,技術必然存在妥協。 業務上需要快速的需求交付,技術上需要架構的可擴展,但速度和質量在工程領域總是存在衝突,而穩定性往往就是問題爆發的衝突點。作爲技術 Leader,你要平衡好這兩種訴求,讓技術與業務協調發展的同時,最大程度確保系統的穩定運行,畢竟“沒有質量的交付,再多再快都毫無意義”。

留個作業: 把最近半年或一年你印象最深刻的事故重新覆盤一遍吧,從事故根因、應急處理以及覆盤改進幾個角度去 Review,未來類似的事故是否還會發生,如果發生你能更好的應對嗎?

最後,感謝你的閱讀,如果這節課讓你有收穫,歡迎你將它分享給其他的朋友,我們下一講見。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章