美團在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...