故障分析| Redis 故障診斷及常用運維命令—內存篇

作者:任仲禹
愛可生 DBA 團隊成員,擅長故障分析和性能優化,文章相關技術問題,歡迎大家一起討論。
本文來源:原創投稿
*愛可生開源社區出品,原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。

本文目錄:
背景
  • Redis 內存消耗劃分
  • 內存 OOM 會導致哪些問題?
排查思路
  • 是否數據量太大?
  • 是否客戶端輸入緩衝區有問題?
  • 是否複製積壓緩衝區有問題?
  • 是否客戶端輸出緩衝區有問題?
實用命令
  • 模擬 Redis 壓力相關命令
  • 常⽤ Redis 內存排查命令
總結

背景

你是否有過這種困擾:我的數據量非常小,但還是報 OOM 錯誤?

# ⼀個簡單set提示內存不⾜
[root@10-186-61-38 redis]# redis-cli -p 9999 set actionsky 1
(error) OOM command not allowed when used memory > 'maxmemory'.

首先我給大家解釋下,Redis 的 OOM 分兩種。

  • ⼀種是因 Redis 使用內存超出 OS 物理內存,OS 將 Redis 進程殺死。

  • 另⼀種是 Redis 使用內存超過 maxmemory 參數配置,引發 Redis Server 層 OOM。

OOM 是 Redis 最常見的內存故障,它影響很大:

  • 故障發生時,進程並不會退出,能讀但無法寫入。

  • 配置了 allkeys-lru、allkeys-lfu 等內存淘汰策略場景下,會有大量鍵失效,導致緩存命中率急劇下降。

本文中,我會給大家分享下該種內存問題的排查方向及運維命令

Redis 內存消耗劃分

簡短介紹下 Redis 內存消耗劃分情況,爲下文診斷提供思路。上圖可以總結 Redis 消耗內存分如下幾塊:

  • 對象內存:理論上佔用最大,存儲所有業務數據,如字符串類型、哈希類型對象等。

  • 客戶端內存:包括輸入客戶端(查詢或寫入命令)、輸出客戶端使用的內存,因爲不受 maxmemory 參數控制,這塊我們需重點排查。

  • 複製積壓緩衝:所有從庫客戶端共享、保存固定大小的寫入命令用於從庫失連後數據補償。

  • Redis 自身內存:存儲數據元數據信息、過期鍵字典等。

  • AOF 緩衝區:AOF 持久化、重寫緩衝區,⼀般佔用很少,基本不需要關注。

內存 OOM 會導致哪些問題?

1. Redis 無法寫入,只能讀取。

2. Redis 大量鍵被逐出內存或過期,導致 Redis 查詢效率降低(maxmemory-policy 配置爲非默認值 noeviction 時)。


排查思路

注意:下文不做特別說明的話,我的 maxmemory 設置爲 1G,其它任何參數爲默認。

是否數據量太大?

使用 redis-benchmark 持續灌入數據,

檢查內存使用情況,發生 OOM 狀態時 used_memory ⼀定會大於 maxmemory。

檢查數據對象內存和其它內存使用情況如下圖:

這裏有必要說明下 overhead.total,它包括除數據外 Redis 消耗的所有內存,比如前面提到的複製緩衝區、客戶端輸入輸出緩衝區等,另外還包括⼀些元數據如 overhead.hashtable,它是數據庫中元數據消耗的內存大小,包括以下三項:

  • 整個數據庫是⼀種 hash 表,首先就是這張 hash 表使用的內存。

  • 每⼀個 key-value 對都有⼀個 dictEntry 來記錄他們的關係,元信息便包含該 db 中所有 dictEntry 使用的內存。

  • redis 使用 redisObject 來描述 value 所對應的不同數據類型(string、list、hash、set、zset),那麼 redisObject 佔用的空間也計算在元數據。

大家對這個現象可能有點疑惑,爲啥我明明設置 maxmemory 爲 1G,你 Redis 只給我存了 990 多 M 數據就滿了?

很好理解,根據上面測試可知數據達到⼀定規模後,因需消耗額外的元數據、緩存內存,Redis 最終將超過 maxmemory 而 OOM。

是否客戶端輸入緩衝區有問題?

製造輸入緩衝區壓力(防止干擾,先清空數據再壓測)

# 關鍵參數解釋
-d 表示每個set值的大小,單位爲字節
-c 啓多少個連接

壓測幾秒鐘後,觸發 OOM,

檢查輸入緩衝區內存消耗,能看到客戶端輸入緩衝區消耗總量爲 2.4G左右,遠遠超過 maxmemory 參數設置。

那我如何找到消耗內存量最大的那個連接呢?

可通過運行上述檢查命令,定位到各客戶端輸入緩衝區的內存消耗(由大到小排序)。

⼀般如果定位到有連接異常,可以使用如下命令殺掉。

# 例如殺掉上圖中 id=51421 的連接
127.0.0.1:9999> CLIENT KILL ID 51421
(integer) 1

是否複製積壓緩衝區有問題?

爲測試方便,我直接把複製積壓緩衝區配置爲 800M。

開啓 redis-benchmark 壓測進程,

檢查複製積壓緩衝區內存消耗,可以看到因爲緩衝區設置過大,數據量才存儲 190 多 M,Redis 就無法寫入了。

是否客戶端輸出緩衝區有問題?

若客戶端輸出緩衝區太大如何排查?⼀般該場景比較少見,常見於用到了 redis 的 monitor 命令。

注意:monitor 命令功能像 MySQL 的 general-log,能打印 Redis 所有執行的命令。在生產環境極少使用或禁用。

先開啓 monitor 命令,

通過 redis-benchmark 製造輸出緩衝區壓力。

測試⼀段時間後觀察 Redis 內存消耗,

此時數據庫無法寫入,

檢查輸出緩衝區各客戶端連接內存消耗、輸出緩衝區總消耗內存如下,

可以看到輸出緩衝區總內存已遠大於 maxmemory 限制,此時內存自然就 OOM。


實用命令

上文排查過程有些 Redis 運維命令我認爲比較實用,整理如下:

模擬 Redis 壓力相關命令

# 1. 持續給Redis灌數據
redis-benchmark -p 9999 -t set -r 100000000 -l
# 2. 模擬輸入緩衝區過大
redis-benchmark -p 9999 -q -c 10 -d 102400000 -n 10000000 -r 50000 -t set
# 3. 模擬輸出緩衝區過大
redis-benchmark -p 9999 -t get -r 5000000 -n 10000000 -d 100 -c 1000 -P 500 -l

常用 Redis 內存排查命令

# 1. 快速查看Redis內存是否夠用
redis-cli -p 9999 info memory |egrep
'(used_memory_human|maxmemory_human|maxmemory_policy)'
# 2. 檢查複製積壓緩衝區使用情況
redis-cli -p 9999 memory stats|egrep -A 1
'(total.allocated|replication.backlog)'
# 3. 檢查客戶端輸入緩衝區內存使用總量
redis-cli -p 9999 client list| awk 'BEGIN{sum=0}
{sum+=substr($12,6);sum+=substr($13,11)}END{print sum}'

# 4. 檢查客戶端輸入緩衝區各客戶端連接的內存情況
redis-cli -p 9999 client list|awk '{print substr($12,6),$1,$12,$18}'|sort -
nrk1,1 | cut -f1 -d" " --complement
# 5. 檢查客戶端輸出緩衝區內存使用總量
redis-cli -p 9999 client list| awk 'BEGIN{sum=0} {sum+=substr($16,6)}END{print
sum}'

# 6. 檢查客戶端輸出緩衝區各客戶端連接的內存使用排序
redis-cli -p 9999 client list|awk '{print substr($16,6),$1,$16,$18}'|sort -
nrk1,1 | cut -f1 -d" " --complement |head -n10
# 7. 檢查數據對象使用內存總量
redis-cli -p 9999 memory stats|grep -A 1 'dataset.bytes'


總結

  • Redis 內存問題大部分可以通過上述排查思路進行定位。

  • 跟大家分享了⼀些常用 Redis 內存排查命令,希望對大家有幫助。

  • 如果大家覺命令執行起來不夠方便,我整理了⼀份 Redis 內存檢查腳本(篇幅稍長)有興趣可以移步查閱:

https://www.jianshu.com/p/a508187bc093

腳本執行效果:


文章推薦:

故障分析 | Redis 內存碎片率太低該怎麼辦?



社區近期動態




本文關鍵字:#Redis# #故障診斷#
  點一下“閱讀原文”瞭解更多資訊

本文分享自微信公衆號 - 愛可生開源社區(ActiontechOSS)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

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