Redis 使用monitor造成的記憶體飆公升

2021-10-24 01:32:01 字數 2677 閱讀 4920

美團在redis上踩過的坑-redis記憶體占用飆公升

redis-cluster某個分片記憶體飆公升,明顯比其他分片高很多,而且持續增長。並且主從的記憶體使用量並不一致。

redis-cluster的bug (這個應該不存在)

客戶端的hash(key)有問題,造成分配不均。(redis使用的是crc16, 不會出現這麼不均的情況)

存在個別大的key-value: 例如乙個包含了幾百萬資料set資料結構(這個有可能)

主從複製出現了問題。

其他原因

經查詢,上述1-4都不存在

觀察info資訊,有一點引起了懷疑: client_longes_output_list有些異常。

於是理解想到服務端和客戶端互動時,分別為每個客戶端設定了輸入緩衝區和輸出緩衝區,這部分如果很大的話也會占用redis伺服器的記憶體。

從上面的client_longest_output_list看,應該是輸出緩衝區占用記憶體較大,也就是有大量的資料從redis伺服器向某些客戶端輸出。於是使用client list命令(類似於mysql processlist) redis-cli -h host -p port client list | grep -v 「omem=0」,來查詢輸出緩衝區不為0的客戶端連線,於是查詢到禍首monitor,於是豁然開朗.

monitor的模型是這樣的,它會將所有在redis伺服器執行的命令進行輸出,通常來講redis伺服器的qps是很高的,也就是如果執行了monitor命令,redis伺服器在monitor這個客戶端的輸出緩衝區又會有大量「存貨」,也就占用了大量redis記憶體。

進行主從切換(主從記憶體使用量不一致),也就是redis-cluster的fail-over操作,繼續觀察新的master是否有異常,通過觀察未出現異常。查詢到真正的原因後,也就是monitor,關閉掉monitor命令的程序後,記憶體很快就降下來了。

為什麼會有monitor這個命令發生,我想原因有兩個:

(1). 工程師想看看究竟有哪些命令在執行,就用了monitor

(2). 工程師對於redis學習的目的,因為進行了redis的託管,工程師只要會用redis就可以了,但是作為技術人員都有學習的好奇心和慾望。

預防方法:

(1) 對工程師培訓,講一講redis使用過程中的坑和禁忌

(2) 對redis雲進行介紹,甚至可以讓有興趣的同學參與進來

(3) 針對client做限制,但是官方也不建議這麼做,官方的預設配置中對於輸出緩衝區沒有限制。

client-output-buffer-limit normal 0 0 0

(4) 密碼:redis的密碼功能較弱,同時多了一次io

(5) 修改客戶端源**,禁止掉一些危險的命令(shutdown, flushall, monitor, keys *),當然還是可以通過redis-cli來完成

(6) 新增command-rename配置,將一些危險的命令(flushall, monitor, keys * , flushdb)做rename,如果有需要的話,找到redis的運維人員處理

以乙個monitor為例,使用redis-benchmark分別測試monitor開啟前後的效能

redis-benchmark -c 10 -n 100000 -q

開啟前結果

ping_inline:

92506.94 requests per second

ping_bulk:

97943.19 requests per second

set:

94786.73 requests per second

get:

99403.58 requests per second

incr:

89766.61 requests per second

開啟後結果

ping_inline:

76569.68 requests per second

ping_bulk:

67294.75 requests per second

set:

44404.97 requests per second

get:

60132.29 requests per second

incr:

49382.71 requests per second

結果對比

開啟後的效能明顯低了很多,例如:

set -53%

get -39%

incr -44%

c 中Monitor的使用

首先lock和minitor有什麼區別呢?其實lock在il 中會被翻譯成monitor。也就是monitor.enter obj 和monitor.exit obj lock obj 等價為 try catch finally 所以lock能做的,monitor肯定能做,monitor能做的,lo...

c 中Monitor的使用

首先lock和minitor有什麼區別呢?其實lock在il 中會被翻譯成monitor。也就是monitor.enter obj 和monitor.exit obj lock obj 等價為 trycatch finally 所以lock能做的,monitor肯定能做,monitor能做的,loc...

c 中Monitor的使用

首先lock和minitor有什麼區別呢?其實lock在il 中會被翻譯成monitor。也就是monitor.enter obj 和monitor.exit obj lock obj 等價為 trycatch finally 所以lock能做的,monitor肯定能做,monitor能做的,loc...