Redis 內存優化

業務場景:Redis 做爲目前主流的key-value 內存數據庫,由於其高併發,存儲查詢速率快,咱們不少的熱點數據均會存儲到Redis 中,若是數據量較大的話,昂貴的內存消耗也是一筆很大的支出,所以Redis 內存優化是頗有必要的。
如下是筆者所在公司的Redis 服務的內存使用狀況

Redis內存使用率.jpg

上圖能夠看到:Redis內部的對象數高達:1,599,098,020(15億),其內存使用高達 371G ,而且持續的增多,須要咱們儘快優化,釋放多餘的空間。
目前存儲的現狀
  • 目前Redis 存儲使用的數據類型爲:string
  • key 的構成爲: type:business_tag:user_id:item_id:item_detail_id
  • value 的組成爲:
{
    "expireTime": "253402271999000",
    "value": "test_test_test_test"
  }
主要優化手段以下
  • 存儲結構變動 由string 變動爲 hash

主要內存優化依據是:
Redis 內部Hash 數據結構的編碼方式主要有兩種:java

  • OBJ_ENCODING_ZIPLIST(壓縮列表)
  • OBJ_ENCODING_HT(哈希表)

Redis 內部會根據數量的狀況自適應的選擇這兩種編碼方式中 最優 的一種,這種操做徹底對用戶透明,選擇壓縮列表存儲的依據主要是:linux

  • 數據條目較少(hash-max-ziplist-entries)即 Hash 的filed 較少 field 個數 默認小於 512
  • 數據值較少(hash-max-ziplist-value)即Hash的value 值較少 value 值的長度小於64

即默認存儲爲壓縮列表存儲的條件爲git

field_num < hash-max-ziplist-entries && value.length < hash-max-ziplist-value

綜上所述:根據前面看到的業務場景,徹底知足此種場景,這是選擇由string存儲變爲 Hash存儲的一個緣由github

OBJ_ENCODING_ZIPLIST 編碼的主要思想是:空間換時間,適應於字段個數比較少,字段值也比較小的場景。
  • key的優化

爲了全方位的對內存進行優化,那麼key 以及 hash 的field 進行必要的壓縮redis

  • 若是是字符串的話能夠進行分段優化,針對數據進行16進制轉換
  • 字符串使用簡寫方式

key_value.png

遷移後Redis 實例存儲對比

爲保證測試的準確性,私有服務器安裝Redis 進行優化前與優化後內存空間測試
如下爲整個測試過程:docker

  • docker 安裝 Redis
docker pull redis

clipboard.png

docker ps # 查詢當前容器

clipboard.png

docker exec -it ****** /bin/bash # 進入容器內部
redis-cli -a 123456 #打開Redis-cli鏈接Redis 
info memory  # 查詢安裝完成後Redis 的內存使用狀況

clipboard.png

以上爲Redis 服務搭建過程的簡單記錄數據庫

  • 數據存儲測試(未優化前)

優化前 存儲 1000000 string 類型數據以下:json

-- string key
0:1:201155:100:545953888100
-- string value
{
  "value": "3.6230093077568726-0.3630194103106919100",
  "expireTime": "2147483647"
}

clipboard.png
由上圖內存存儲可知:未優化前 1000000 條 string 消耗內存:200.12M
執行完測試,將此前存入的數據刪除bash

clipboard.png

  • (1)數據存儲測試(優化key value)服務器

    • 壓縮key的長度:將最後的無業務標識的字符串轉換爲:16進制
    • 壓縮value 的長度:壓縮value的數據

clipboard.png
優化後 存儲1000000數據使用內存:139.10M 相比較優化前優化內存:30%
偷偷竊喜下,若是進行這次優化:節省內存:115G

  • (2)數據存儲測試(優化key value)

    • 壓縮key的長度:將最後的無業務標識的字符串轉換爲:64 進制
    • 壓縮value 的長度:壓縮value的數據

clipboard.png
這次優化變化不明顯,僅僅下降了 不到1M ,疑惑臉。。。
因而乎對於key的長度不進行壓縮,只對value值進行壓縮進行測試結果以下:

clipboard.png
由以上測試可得:1000000數據,內存使用率爲 146.59M ,故此 16/64 進制對key的壓縮影響並不明顯。

  • (3)數據存儲測試(優化key value)

    • 壓縮key的長度:將最後的無業務標識的字符串轉換爲:64 進制
    • 壓縮value 的長度:壓縮value的數據,不在存儲json,只存儲,attr1:value,attr2:value2

clipboard.png

以上優化後,存儲1000000數據使用內存:123.86M,優化達到:38%

  • (4)數據存儲測試(優化key value)

    • 壓縮key的長度:將最後的無業務標識的字符串轉換爲:64 進制
    • 壓縮value 的長度:壓縮value的數據,不在存儲json,只存儲,attr1:value

clipboard.png
通過第4次進行優化,內存的佔用依舊與第三次相差很小,可是仍然在減小,這次內存佔用爲 123.71M,繼續對value值作壓縮

  • (5)數據存儲測試(優化key value)

    • 壓縮key的長度:將最後的無業務標識的字符串轉換爲:64 進制
    • 壓縮value 的長度:壓縮value的數據,只存儲,attr1:value, exp(過時時間戳)壓縮爲64進制

clipboard.png
通過第5次進行優化,內存佔用達到了 116.27M ,優化達到:42%

  • 數據存儲測試(優化key value的基礎上進行 數據結構變動:變動爲HASH)

clipboard.png

見證奇蹟的時刻到了,變動HASH 結構後,1000000數據內存佔用 100.49M,優化50%

思考:

Redis 的內存優化,須要配合業務場景進行鍼對性的優化,並非一味的已減小內存爲主要的優化目標,咱們也應該在空間和時間上找到一個平衡點進行恰當的優化,就那這次優化來講,雖然內存減小了 50% ,可是在實際應用中考慮到,該數據對於效率要求比較高,因此在進行編碼解碼過程當中也存在時間的消耗,最終並非採用內存優化度最大的那種方案。

這次測試的代碼都可在github 傳送門: 項目測試
相關文章
相關標籤/搜索