Redis開發與運維之第八章理解內存(五)

insert編碼

是集合(set)的類型編碼的一種,內部表現爲存儲有序、不重複的整數集。當集合只包含整數且長度不超過set-max-intset-entries 配置時被啓用。執行以下命令查看intset表現:

redis> sadd set:test 3 4 2 6 8 9 2
(integer) 6
redis> object encoding set:test
"intset"
redis> smembers set:test
"2" "3" "4" "6" "8" "9"
redis> config set set-max-intset-entries 6
OK
redis> sadd set:test 5
"hashtable"
redis> smembers set:test
"8" "3" "5" "9" "4" "2" "6"

以上命令可以看出intset對寫入整數進行排序,通過O(logn)時間複雜度實現查找和去重操作,intset編碼結構如圖所示:

  

字段結構含義:

1. encoding:整數表示類型,根據結合內最長整數值確定類型,整數類型劃分爲三種,int-16/int-32/int-64

2. length:表示集合元素個數。

3. contents: 整數數組、按從小到大順序保存。

intset保存的整數類型根據長度劃分,當保存的整數超出當前類型時,將會觸發自動升級操作且升級後不再做回退。

升級操作將會導致重新申請內存空間,把原有數據按轉換類型後拷貝到新數組中。

控制鍵的數量

當使用redis存儲大量數據時,通常會存在大量鍵,過多的鍵同樣會消耗大量內存。Redis本質是一個數據結構服務器,它爲我們提供多種數據結構,如hash、list、set、zset等。使用Redis時不要進入一個誤區,大量使用get/set/這樣的API,把redis當錯memcached使用。

對於存儲相同的數據內容利用Redis的數據結構降低外層鍵的數量,也可以節省大量內存。如圖所示,通過在客戶端預估鍵規模,把大量鍵分組映射到多個hash結構中減低鍵的數量。

 hash結構降低鍵數量分析:

1. 根據鍵規模在客戶端通過分組映射到一組hash對象中,如存在100萬個鍵,可以映射到1000個hash中,每個hash保存1000個元素。

2. hash的field可用於記錄原始key字符串,方便哈希查找。

3. hash的value保存原始值對象,確保不要超過hash-max-ziplist-value限制。

同樣的數據使用ziplist編碼的hash類型存儲比string類型節約內存。

節省內存量隨着value空間的減少越來越明顯。

hash-ziplist類型比string類型寫入耗時,但隨着value空間的減少,耗時逐漸降低。

使用hash重構後節省內存量效果非常明顯,特別對於存儲小對象的場景,內存只有不到原來的1/5 。下面分析這種內存優化技巧的關鍵點;

1. hash類型節省內存的原理是使用ziplist編碼,如果使用hashtable編碼方式反而會增加內存消耗。

2  ziplist長度需要控制在1000以內,否則由於存儲操作時間複雜度在O(n) 到O(n2)之間,長列表會導致CPU消耗嚴重,得不償失。

3. ziplist適合存儲小對象,對於大對象不但內存優化效果不明顯還會增加命令操作耗時。

4. 需要預估鍵的規模,從而確定每個hash結構需要存儲的元素數量

5. 根據hash長度和元素大小,調整hash-max-ziplist-entries和hash-max-ziplist-value參數,確保hash類型使用ziplist編碼

關於hash鍵和field鍵的設計:

1. 當鍵離散度較高時,可以按字符串位截取,把後三位作爲哈希的field,之前部分作爲哈希的鍵。

如:key=1948480哈希key=group:hash:1948,哈希field=480。

2. 當鍵離散度較低時,可以使用哈希算法打散鍵,

如:使用crc32(key)&10000函數把所有的鍵映射到“0-9999”整數範圍內,哈希field存儲鍵的原始值。

3. 儘量減少hash鍵和field的長度,如使用部分鍵內容

使用hash結構控制鍵的規模雖然可以大幅降低內存,但同樣會帶來問題,需要提前做好規避處理

1. 客戶端需要預估鍵的規模並設計hash分組規則,加重客戶端開發成本。

2. hash重構後所有的鍵無法再使用超時(expire)和LRU淘汰機制自動刪除,需要手動維護刪除

3. 對於大對象,如1KB以上的對象,使用hash-ziplist結構控制鍵數量反而得不償失

4. 對於大量小對象的存儲場景,非常適合使用ziplist編碼的hash類型控制鍵的規模來降低內存

使用ziplist+hash優化keys後,如果想使用超時刪除功能,開發人員可以存儲每個對象寫入的時間,再通過定時任務使用hscan命令掃描數據,找出hash內超時的數據項刪除即可

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章