快看,咱們的分佈式緩存就是這樣把註冊中心搞崩的!

文章轉自公衆號:吃草的羅漢


掃描下方海報二維碼,試聽課程:
node

(課程詳細大綱,請參見文末)面試

寫公衆號兩年以來,每當有機會寫故障類主題的時候,我都會在開始前靜靜地望着顯示器好久,通過屢次煎熬和掙扎以後纔敢提起筆來緩存

爲何呢?由於這樣的話題很容易招來吐槽,好比 「說了半天,不就是配置沒配好嗎?」,或者 「這代碼是豬寫的嗎?大家團隊有懂性能測試的同窗嗎?」網絡

這樣的評論略帶挑釁,並且充滿了鄙視之意。
架構

不過我以爲,在技術的世界裏,多數狀況都是客觀場景決定了主觀結果,而主觀結果又反映了客觀場景運維

可以把場景與結果串起來,用本身的方式寫下來,傳播出去,與有相同經歷的同窗聊上一聊,也何嘗不是一件好事。分佈式

上個月,咱們的系統因註冊中心崩塌而引起的一場事故,本是一件稀鬆日常的事件,可咱們猜中了開始卻沒料到緣由,始做俑者竟是已在產線運行多年的某分佈式緩存系統。性能

這究竟是怎麼一回事呢?測試

先來回顧一下故障過程設計

11月,某交易日的上午10點左右。

在中間件監控系統沒有觸發任何報警的狀況下,某應用團隊負責人忽然跑過來講:「怎麼緩存響應怎麼慢?大家在幹什麼事嗎?」

因爲此正在交易盤中,中間件運維團隊瞬間炸鍋,緊急查看了一系列監控數據

先是經過Zabbix查看了如CPU、內存、網絡及磁盤等基礎預警,一切正常,再查看服務健康情況,通過一圈折騰以後,也沒發現任何疑點。

懵圈了,沒道理啊。

10點30分,收到一通報警信息,內容爲 「ZK集羣中的某一個節點故障,端口不通,不能獲取node信息,請迅速處理!」

這簡單,ZK服務端口不通,重啓,當即恢復。

10點40分,ZK集羣所有癱瘓,沒法獲取Node數據,因爲應用系統的Dubbo服務與分佈式緩存使用的是同一套ZK集羣,並且在此期間應用未重啓過,所以應用服務自身暫時未受到影響。

沒道理啊,不管應用側仍是緩存側,近一個月以來都沒有發佈過版本,並且分佈式緩存除了在ZK中存一些節點相關信息以外,基本對ZK無依賴。

10點50分,ZK集羣所有重啓,10分鐘後,再次癱瘓。

神奇了,到底哪裏出了問題呢?

10點55分,ZK集羣所有重啓,1分鐘後,發現Node Count達到近22W+,再次崩潰。

10點58分,經過增長監控腳本,查明Node源頭來自分佈式緩存系統的本地緩存服務

11點00分,經過控制檯關閉本地緩存服務後,ZK集羣第三次重啓,經過腳本刪除本地化緩存所產生的大量node信息。

11點05分,產線ZK集羣所有恢復,無異常。

一場風波雖然說過去了,但每一個人的臉上流露出茫然的表情,邪了門了,這本地緩存爲何能把註冊中心搞崩塌?都上線一年多了,以前爲何不出問題?爲何恰恰今天出事?

一堆的問好,充斥着每一個人的大腦。


咱們本地緩存的工做機制

去年,我曾經在 #好買的分佈式緩存中間件# 的內容中對咱們的分佈式緩存作過相對詳細的說明,因此在這裏,我就經過系統流程示意圖的方式,簡要的說明下咱們本地緩存系統的一些核心工做機制。

| 非本地緩存的工做機制


| 本地緩存的工做機制 - KEY預加載/更新


| 本地緩存的工做機制 - Set/Delete操做


| 本地緩存的工做機制 - Get操做

順帶提一句,因爲歷史性與資源緊缺的緣由,咱們部分緩存系統與應用系統的ZK集羣是混用的,正因如此,給本次事故埋下了隱患。

ZK集羣是怎樣被搞掛的呢?

說到這裏,相信對中間件有必定了解的人基本能猜出本事件的全貌。

簡單來講,就是在上線初期,因爲流量小,應用系統接入量小,咱們本地緩存的消息通知是利用ZK來實現的,並且還用到了廣播。

但隨着流量的增長與應用系統接入量的增多,消息發送量成倍增加,最終達到承載能力的上限,ZK集羣崩潰。

的確,緣由基本猜對了,但消息發送量爲何會成倍的增加呢?

根據本地緩存的工做機制,咱們通常會在裏面存些什麼呢?

  1. 更新頻率較低,但訪問卻很頻繁,好比系統參數或業務參數。

  2. 單個Key/Value較大,網絡消耗比較大,性能降低明顯。

  3. 服務端資源匱乏或不穩定(如I/O),但對穩定性要求極高。

懵圈了,就放些參數類信息,並且更新頻率極低,這樣就把五個節點的ZK集羣發爆了?

爲了找到真相,咱們當即進行了代碼走讀,最終發現了蹊蹺。

根據設計,在 「本地緩存的工做機制 - Set/Delete操做」 的工做機制中,當一個Key完成服務端緩存操做後,若是沒有被加到本地緩存規則列表中的KEY,是不可能被觸發消息通知的

但這裏明顯存在BUG,致使把全部的KEY都發到了ZK中。

這樣就很好理解了,雖然應用系統近期沒有發佈版本,但卻經過緩存控制檯,悄悄地把分佈式鎖加到了這套緩存分片中

因此交易一開盤,只需幾十分鐘,立馬打爆。

另外,除了發現BUG以外,經過過後測試驗證,咱們還得出瞭如下幾點結論:

  1. 利用ZK進行消息同步,ZK自己的負載能力較弱,是否切換到MQ?

  2. 監控手段的單一,監控的薄弱;

  3. 系統部署結構不合理,基礎架構的ZK不該該與應用的ZK混用;


說到這裏,這個故事也該結束了。

講在最後

看完這個故事,一些愛好懟人的小夥伴也許會忍不住發問。大家本身設計的架構,大家本身編寫的代碼,難道不知道其中的邏輯嗎?這麼低級的錯誤,竟然還有臉拿出來講?

那可未必,對每一個技術團隊而言,核心成員的離職與業務形態的變化,都或多或少會引起技術團隊對現有系統造成 「知其然而,殊不知其因此然」 的狀況,雖然說每一個團隊都在千方百計進行避免,但想徹底杜絕,絕非易事。

做爲技術管理者,具有良好的心態,把每次故障都當作是一次蟬變的過程,從中獲得總結與經驗,並加以傳承,從此再也不就犯,那就是好樣的。

不過,萬一哪天失手,給系統來了個完全癱瘓,該怎麼辦呢?

祝你們一切順利吧。


END

《21天互聯網Java進階面試訓練營(分佈式篇)》詳細目錄,掃描圖片末尾的二維碼,試聽課程

相關文章
相關標籤/搜索