看到Redis報了OOM的錯誤,並且服務響應速度很是慢,頁面上丟了不少數據,趕忙起來查看問題。redis
咱們的系統架構是雙邊雙活的,兩個DC都會有數據寫進來,經過API把數據存到數據庫(雙邊數據庫有複製),同時寫到Redis隊列一份(這裏把Redis當成MQ來用),而後有個Job從redis隊列裏面把數據取出來,寫到兩邊,流式地處理數據。對於Redis隊列來講,API是生產者,Job是消費者。此次只是GSB這邊的Redis出了問題,致使了單邊不可用。數據庫
通常Redis裏的元數據大小是比較穩定的,出現OOM應該先看隊列的大小。果真這個數據隊列的size已經遠遠超過了閾值。咱們先把隊列清空了,而後把數據讀取從Redis切換到了DB,GSB側終於能正常工做了。緩存
如今咱們的數據量通常是每秒鐘三四百條左右,按理來講Job的消費速度確定是能跟上的。可是看問題側(GSB側)隊列大小大體呈每秒鐘一百條的速度在遞增。看了一下GSB側Job的log,發現消費速度很不穩定,最慢的時候一秒鐘只能處理三四十條。按照Redis官方百萬級的QPS,這簡直能夠用龜速來形容了。接下來咱們來看具體慢在哪裏。能夠用網絡
redis-cli --latency -h `host` -p `port`架構
命令來查看命令的延遲狀況,此命令會不斷給Redis發ping命令而後統計響應時間。先來看本機延時對比:ide
Primary本機延時性能
GSB本機延時spa
經過在Redis本機上經過latency的對比,發現Primary側和GSB側的延時接近一致,一個是0.04ms,一個是0.05ms,看來瓶頸不在Redis自己。再來對比一下從其餘機器上連Redis的延時狀況:3d
Primary網絡延時blog
GSB網絡延時
能夠看出來,GSB側的Redis響應速度明顯比Primary側的慢,一個是0.37ms,一個是1.67ms,有近四五倍的差距。可是按理來講網絡速度慢,應該影響到生產者和消費者雙方,爲何數據仍是能不斷堆積呢?這是由於咱們API有四臺機器,而Job只有一臺機器,致使了消費速度跟不上。
找到了root cause以後,趕忙聯繫Network Team,被告知GSB側有一個Network的Incident,估計就是此次問題的元兇了。咱們改了一下代碼,檢測若是隊列大小超過必定的閾值,就刪除一部分數據。雖然會致使部分緩存數據的丟失,可是爲了避免影響到系統的總體可用性,也只能這麼作了。
果真次日,Incident結束了以後,Job的消費速度就恢復正常了。
網絡問題致使Redis的響應時間變慢,並且生產者數量比消費者數量多,致使Redis隊列數據消費不完,隊列堆積,從而OOM。經過此次事件,咱們獲得教訓:
1. 最好不要用Redis作MQ來用,不然當隊列堆積會形成Redis總體不可用,最終致使系統不可用。
2. 生產者和消費者的數量要大體對等,不然要麼會出現任務堆積,要麼會出現性能資源浪費。