摘要:後端模塊批量重啓,重啓時需要從數據庫加載業務數據,因併發重啓且該請求爲慢SQL(幾十秒),雲數據庫負載快速升高,部分請求開始超時,然後請求失敗的模塊無限重試,導致雲數據庫負載過大而崩潰,依賴該數據庫的其他業務也全部故障。沒上雲之前,可能會有專門的DBA團隊來對數據庫進行監控,上雲後,如果沒有專職的DBA,那麼業務運維團隊就需要承擔起這個責任來。

責任共擔模型

朋友和我吐槽,自從他負責的系統上雲後,在雲數據庫上經歷了好幾次故障,而事後的故障覆盤,居然都是他們自己的責任和問題,這讓他很被動。更尷尬的是,原想着上雲後,數據庫的問題都是公有云廠商負責,所以他們運維團隊中也沒有招聘DBA,當下沒有很好的優化思路,於是找我一起探討這個問題。

朋友的這個Case很典型,認爲上雲就萬事大吉,上雲後一旦出現問題,又會覺得上雲各種不靠譜。在公有云廠商中,被大家廣爲認可的觀點是“責任共擔模型“ 在海外,亞馬遜AWS、微軟Azure均採用了與用戶共擔風險的安全策略。例如,AWS 作爲IaaS+PaaS爲主的服務提供商,負責管理雲本身的安全,業務系統安全則由客戶負責。客戶可以在AWS安全市場裏挑選合適的產品來保護自己的內容、平臺、應用程序、系統和網絡安全。而微軟Azure也探討了IaaS, PaaS和SaaS用戶的“責任遞減”模式。在這裏,我們並不打算展開討論該問題,只是希望引入該概念,讓大家建立初步的認知:上雲後,依然是需要客戶和平臺雙方通力合作才能取得好的結果。

上雲後他經歷了什麼?

下面是朋友講述的故障,限於故障原因的重複,我刪減了一些Case,聽朋友講完後,我非常喫驚,心裏暗想,這和上雲有啥關係,這些問題,你不上雲照樣都會發生的,只能說你運氣好,發生在上雲期間,大家對於新事物多少有一些寬容,不然,後果不敢想啊。

  • 後端模塊批量重啓,重啓時需要從數據庫加載業務數據,因併發重啓且該請求爲慢SQL(幾十秒),雲數據庫負載快速升高,部分請求開始超時,然後請求失敗的模塊無限重試,導致雲數據庫負載過大而崩潰,依賴該數據庫的其他業務也全部故障

  • 在短時間大量併發請求數據庫,高峯期併發達到2200左右,導致數據庫出現大量慢SQL,進而數據庫性能急劇下降,多個業務頁面展現變慢,性能退化明顯

  • 批量創建的任務,其執行時間完全一致,系統在瞬間對數據庫請求大量數據,連接數上漲,導致該數據庫上的所有業務均發生故障

  • 一次秒殺活動,系統請求量劇增,峯值流量達到平時流量的30倍,遠超之前預估流量。部分功能大量請求數據庫,佔滿數據庫鏈接,導致數據庫崩潰,進而引起系統無法正常運行

  • 其購買的安全掃描產品,對接口進行了空參數請求,而接口對於空參數請求進行了數據庫的全表掃描,數據庫壓力飆升,陸續出現了慢SQL,數據庫CPU使用率持續在100%,導致該數據庫上的其他業務也全部故障

  • 某服務訪問數據庫錯誤導致響應下游請求合法用戶列表的結果爲空值,下游模塊直接將所有用戶的權限全部刪除,導致系統完全不可用

  • 沒有專職DBA,雲數據庫的變更直接交由研發自己執行,研發多次數據庫修改出現異常,導致服務故障和數據丟失

  • 研發懷疑數據庫性能惡化,因此就重啓了數據庫,重啓期間,有一個模塊請求數據庫失敗,就直接崩潰了

  • 在華南部署的一套業務系統,連到華北的數據庫,導致系統的響應時間長期居高不下,原因是一個頁面包含了非常多的數據庫請求,單個請求延時增加40ms,但幾十個請求串行執行,延時足足增加了2s以上

故障原因分析

和京東雲平臺質量部的同學們對上述的Case進行分析後,我們總結了以下原因

慢SQL

常態下系統中存在很多慢SQL,其執行時間少則15s,多則60s以上,如果慢SQL的執行次數增加,必然導致雲數據庫壓力上升,數據庫連接被佔用,處理其他請求的速率也慢了下來,直至連接數被耗光,導致服務異常,或者在連接數沒耗光之前,就因爲數據庫CPU使用率100%而導致服務異常了

高頻SQL

高頻SQL看似沒有問題,但延時一旦增加或者網絡抖動,高頻SQL就可能變爲較慢的SQL,基於其基礎足夠大,足以將系統拖垮

複用

上面的多次故障都是因爲某一個業務異常導致數據庫故障後,影響到了數據庫上的所有業務,這可能是源於期望降低運維複雜度,所以搞了一個最大規格數據庫的原因,確實,所有業務共用一個數據庫從管理角度肯定更簡單

讀寫未分離

上述的Case,大部分都是讀請求導致的故障,突然間因爲各種原因,導致請求上漲,而數據庫實例只有一個,沒有水平擴展,所以很容易被打掛

數據庫連接數設置不合理

從故障描述中可以看到,隨便一個請求,都可以把數據庫的併發連接數打到2000+以上,進而導致其他業務不可用,沒有對不同業務進行合理的資源分配

缺乏變更流程

研發直接到線上數據庫中修改數據,修改錯誤的原因有表的名字錯了,where條件錯了,或者是對較大的表結構進行調整,操作前不在線下進行測試驗證,操作前也不進行數據庫備份,很容易導致重大事故

權限管理混亂

多個CASE都是研發直接操作線上數據,這是權限管理混亂的表現,也是很危險的事情。試想,人人都能修改數據庫,會有什麼後果大家應該都很清楚。如果修改了和交易數據相關的數據,或者是刪庫跑路,那就麻煩了

不限流

多個CASE也都看到這個問題,所有的接口都沒有做限流,大家可以發起隨意量級的訪問,因此隨便一個用戶發起批量請求都足以將系統打垮

雲平臺質量部的建議

結合該朋友的情況,雲平臺質量部的同學經過討論後,對數據庫的改進給出如下建議,而對於一些較爲通用的問題,如系統異常後直接崩潰,空參數等等,則不在此進行討論,我們後續會有專門的文章進行說明

TOP-N的SQL限流

TOP-N的SQL分爲兩種情形:

  • 慢SQL,也就是執行耗時的TOP-N

    • SQL優化

    • 合理設置數據庫連接數

    • 執行耗時超過1s的SQL直接kill(對於部分場景可以進行自定義,如同步任務,寫SQL,重要性較高的SQL等)

    • SQL問題較多的賬號進行緊急封禁

  • 高頻SQL,也就是執行頻次的TOP-N

    • 通過業務層的緩存功能減少高頻SQL

在京東雲上,提供了性能優化的功能,可以查詢到所有的慢SQL,一定要加以使用

最後提一句,一定要想辦法在集羣上實現自動化kill慢SQL的功能,而不要等遇到出問題後挨個找人來看能不能殺這些SQL,那就太晚了,經驗值,一旦走到這個地步,故障時長起步40分鐘。

隔離部署

核心業務必須使用獨立的數據庫實例,僅非核心業務可以考慮共用數據庫實例。從而避免單個用戶的問題影響到所有業務。但隔離不僅僅是基於業務角度進行隔離,還可以根據業務情況進行其他維度的隔離,例如將一些報表類業務從核心業務中剝離出來,類似的思路,業務運維 的隔離方式有很多,可以參考《任務調度系統如何通過隔離提升可用性?》

從成本角度看,京東雲很好的考慮到了這點,兩個小實例的價格等於一個大實例的價格,因此拆分並不會增加費用,而管理成本的增加也非常低。

讀寫分離

京東雲的雲數據庫提供只讀實例,需要利用好該特性。簡單點就是新增幾個只讀實例將讀請求進行遷移,複雜點,可以將不同業務類型的讀請求分配到不同的只讀實例上,利用隔離的特性將故障控制在較小的範圍內,從而保障大部分功能的正常使用。

限流

流不僅僅在數據庫層面通過連接數的方式進行控制,更需要前置在業務側進 行,畢竟 業務側的限流機制會更爲靈活和定製化 ,更能滿足業務的需求。如何限流,可以參考《預案三板斧的限流大法》

數據備份

對數據庫的任何修改和調整,都需要進行備份,以免發生上述朋友的問題。京東雲提供了靈活的數據庫備份管理功能,需要好好的使用起來。這個地方的重要性,就不贅述了。

數據庫的監控

沒上雲之前,可能會有專門的DBA團隊來對數據庫進行監控,上雲後,如果沒有專職的DBA,那麼業務運維團隊就需要承擔起這個責任來。下面是從京東雲的監控中截取的幾個關鍵指標,當然,還需要有對數據庫功能的監控。在這點上,雲平臺質量部有較爲豐富的經驗,大家也可以參考《監控不到位,宕機兩行淚》

流程建立

對於變更和權限管理等,都需要逐步建立起相關的流程,並儘量自動化起來。同時,針對各種高頻操作,還可以提供如操作手冊,checklist手冊等,儘量減少手工操作。

我個人的習慣,任何問題,提供了多 個解決方案後,最後都要通過三板斧來進行優先級排序,便於大家抓住重點

  • 隔離部署&&讀寫分離,利用京東雲的能力,可以快速搞定,所以放第一位

  • TOP-N的SQL,找出來容易,優化則需要研發配合,因此放第二位,可以先從那些執行時間幾十秒的SQL開始下手

  • 限流,或者在接入層進行,或者核心模塊上進行開發,耗時略長,因此放第三位

最後,感謝平臺質量部的多個小夥伴一起羣策羣力完成的上述方案。

參考文獻:

任務調度系統如何通過隔離提升可用性

https://www.infoq.cn/article/vsb2jGCAgXPPdqPS38S6

預案三板斧的限流大法

https://www.infoq.cn/article/L1FThcLIgzHSYlIaDk0R

監控不到位,宕機兩行淚

https://www.infoq.cn/article/txmNQW_d7Hpi8KyXf4wz

責任共擔模型

https://aws.amazon.com/cn/compliance/shared-responsibility-model/

相關文章