版權聲明:本文為博主原創文章,遵循 CC 4.0 by-sa 版權協議,轉載請附上原文出處連結和本聲明。
本文連結:https://blog.csdn.net/smartbetter/article/details/97971392
本篇主要介紹 Redis 內存優化的一些技巧。
1.內存消耗
1、內存使用統計
Redis 可以通過 info memory 命令來查看內存使用情況,屬性說明如下:
2、內存消耗劃分
2.緩衝內存
1.客戶端緩衝區
客戶端分為普通客戶端(Jedis)、slave 客戶端、pubsub 客戶端。
輸入緩衝區:
流程:客戶端 -> 命令(輸入緩衝區) -> 處理命令
注意:最大 1GB,超過後會被強制斷開,不可動態設置。
輸出緩衝區:
輸出緩衝區對應的配置規則是:client-output-buffer-limit < class> < hard limit> < soft limit> < soft seconds>
< class>:客戶端類型,分為三種(a)normal 普通客戶端;(b)slave 從節點用於複製,偽裝成客戶端;(c)pubsub 發布訂閱客戶端。
< hard limit>:如果客戶端使用的輸出緩衝區大於 < hard limit>,客戶端會被立即關閉。
< soft limit> 和 < soft seconds>:如果客戶端使用的輸出緩衝區超過了 < soft limit> 並且持續了 < soft limit> 秒,客戶端會被立即關閉。
普通客戶端(Jedis)默認 client-output-buffer-limit normal 0 0 0,默認沒有限制客戶端緩衝,注意防止大的命令或者 monitor。
slave 客戶端默認 client-output-buffer-limit slave 256mb 64mb 60,注意從節點不要超過 2 個。
pubsub 客戶端默認 client-output-buffer-limit pubsub 32mb 8mb 60,使用場景並不多,注意根據實際場景適當調試。
2.複製緩衝區
此部分內存獨享,考慮部分複製,默認 1 MB,可以設置更大。
3.AOF 緩衝區
AOF 重寫期間,AOF 的緩衝區沒有容量限制。
3.對象內存
key對象:不要過長,量大不容忽視;
value對象:ziplist、intset 等優化方式。
4.內存管理
1.內存設置上限
定義實例最大內存,便於管理機器內存,一般要預留 30%。動態調整內存上限的命令:
\tredis> config set maxmemory 6GB
\tredis> config rewrite
2.內存回收策略
- 1、刪除過期鍵值
惰性刪除:訪問 key -> expired dict -> del key
定時刪除:每秒運行 10 次,採樣刪除。
- 2、內存溢出控制策略
超過 maxmemory 後觸發相應策略,由 maxmemory-policy 控制。
- Noeviction:默認策略,不會刪除任何數據,拒絕所有寫入操作並返回錯誤信息 「(error) OOM command not allowed when used memory」,此時 Redis 只響應讀操作由 maxmemory-policy 控制。
- Volatile-lru:根據 LRU 算法刪除設置了超時屬性(expire)的鍵,直到騰出足夠空間為止,如果沒有可刪除的鍵對象,回退到 Noeviction 策略。
- Allkeys-lru:根據 LRU 算法刪除鍵,不管數據有沒有設置超時屬性,直到騰出足夠空間為止。
- Allkeys-random:隨機刪除所有鍵,直到騰出足夠空間為止。
- Volatile-random:隨機刪除過期鍵,直到騰出足夠空間為止。
- Volatile-ttl:根據鍵值對象的 ttl 屬性,刪除最近將要過期的數據,如果沒有,回退到 Noeviction 策略。
5.內存優化
1、合理的選擇優化數據結構
2、客戶端緩衝區內存優化
示例:一次內存暴增。Redis Sentinel 架構,maxmemory 設置為 4GB,發現主節點使用內存 4GB,從節點使用內存 2GB。
排查過程:主節點是否有大批量的寫入?查看監控發現沒有。
主從不一致?主從都執行 dbsize 命令,發現都是 23254136。
客戶端溢出?實際上已經收到報警了,最大輸出緩衝區溢出了,這個時候我們完全可以使用 client list 命令找到 omem 為 0 的客戶端連接:
\tredis-cli client list | grep -v "omem=0"
發現有一個 oll=201261 omem=4675586842 cmd=monitor 的連接,根據 cmd==monitor 判斷執行來源是 monitor,monitor 拉取了那麼大數據,但是自身消費不了,這個時候我們可以將 monitor 直接幹掉,進行內存回收。
預防策略:
- 運維層面:線上 Redis 禁用 monitor(rename-command)命令;適度限制緩衝區大小;
- 開發層面:理解 monitor 原理,也可以短暫尋找熱點 key(本地執行);使用 CacheCloud 可以直接監控到。
3、其他方法
- 不要忽視 key 的長度,1 億個鍵,1 個位元組也是節省;
- 序列化和壓縮方法,拒絕 java 原生,採用 protobuf、keyo、snappy 等。