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內超時的數據項刪除即可
?
?
總結
以上是生活随笔為你收集整理的Redis开发与运维之第八章理解内存(五)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 绝对定位和浮动的区别和运用
- 下一篇: mysql: 模糊查询 feild li