由Redis的hGetAll函數所引發的一次服務宕機事件


昨晚通宵生產壓測,終於算是將生產服務宕機的原因定位到了,心累。這篇博客,算作一個復盤和記錄吧。。。

 

先來看看Redis的緩存淘汰算法思維導圖:

說明:當實際占用的內存超過Redis配置的maxmemory時,Redis就會根據用戶選擇淘汰策略清除被選中的key。

 

業務場景:用戶通過微信入口來訪問一個頁面;

測試場景:通過多線程模擬定量的並發來訪問頁面服務;

涉及架構:springsession+Redis集群,容器部署;

問題描述:固定並發數壓測10分鍾,壓測開始后半小時,Redis連接數激增,連接耗盡,服務重啟;

處理邏輯:

①、用戶通過入口頁面訪問服務時,springsession給每個用戶創建一個session,將key存儲在Redis中;

②、Redis默認配置每隔半小時,利用hGetAll函數遍歷session-key所在的集合,將最近一分鍾內要過期的key全部delete,釋放內存;

宕機原因:

①、Redis是單線程處理,由於高並發壓測,產生了百萬級的key存儲在set集合中,當hGetAll函數遍歷集合刪除過期session的key時,大量用戶連接失效;

②、失效瞬間,Redis需要創建大量連接,如果新建連接數超過了設置的最大連接數,則Redis服務容器健康檢查不通過;

③、通過選舉,Redis集群主從切換時需要將master的數據復制到salve;

④、主從復制時,Redis定位區域buffer(軟鏈接)超時,最終導致服務宕機重啟。

優化方案:

①、選擇Redis默認淘汰策略,每秒鍾選擇10次,每次不超過25個,即每秒鍾淘汰≤250個key;

缺點:內存耗用較高,需要通過橫向擴展資源來應對該問題;

②、通過壓測確定當前系統配置下的最大可處理閾值,通過網關限流、服務降級等措施來保障服務的穩定運行;

缺點:如果實際流量超過限流配置,則用戶可能看到一些“友好界面”,用戶體驗不太好;

③、新建一個單獨工程定期清理過期key,修改工程實例與Redis的消息訂閱事件邏輯,降低OPS與client connect,Redis由哨兵改集群模式;

說明:方案③與方案②結合,可大大提高系統的可用性!!!

PS:在實際生產環境中,系統穩定性和可用性勝於一切!!!

相關參考:

Redis緩存淘汰算法

Redis的hGetAll函數的性能問題

 

以上就是此次問題復盤,雖然通宵帶來的后遺症導致現在還有點迷糊,但從中學到了很多新的東西,值得思考與學習。。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM