Redis 分布式實踐——內存優化

2019-08-21   零聲度7

版權聲明:本文為博主原創文章,遵循 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 等。