Redis开发与运维之第八章理解内存(四)
編碼優化
1.了解編碼
Redis對外提供了string list hash set zet 等類型,但是Redis內部針對不同類型存在編碼概念,所謂編碼就是具體使用哪種底層數據結構來實現。編碼不同將直接影響數據的內存占用和讀寫效率。使用object encoding 命令獲取編碼類型。
redis> set str:1 hello OK redis> object encoding str:1 "embstr*" redis> lpush list:1 1 2 3 (integer) 3 redis> object encoding list:1 "ziplist"作者通過不同編碼實現效率和空間的平衡。比如當我們的存儲只有10個元素的列表,當使用雙向鏈表數據結構時,必然需要維護大量的內部字段如每個元素需要:前置指針,后置指針,數據指針等,造成空間浪費,如果采用連續內存結構的壓縮列表(ziplist)將會節省大量內存而由于數據長度較小,存取操作時間復雜度即使為O(n2)
2.控制編碼類型
編碼類型轉換在Redis寫入數據時自動完成,這個轉換過程是不可逆的。轉換規則只能從小內存編碼向大內存編碼轉換。
redis> lpush list:1 a b c d (integer) 4 redis> object encoding list:1 "ziplist" redis> config set list-max-ziplist-entries 4 OK redis> lpush list:1 e (integer) 5 //寫入第五個元素e redis> object encoding list以上命令體現了list類型編碼的轉換過程,其實Redis之所以不支持 編碼回退,主要是數據增刪頻繁時,數據向壓縮編碼轉換非常消耗CPU,得不償失。以上實例用到了list-max-ziplist-entries 參數,這個參數用來決定列表長度在多少范圍內使用ziplist編碼。
?編碼轉換流程
可以使用config set 命令設置編碼相關參數來滿足使用壓縮編碼條件。對于已經采用非壓縮編碼類型的數據如hashtable,linkedlist等,設置參數后及時數據滿足壓縮編碼調試,redis也不會轉換,需要重啟Redis重新加載數據才能完成轉換。
3. ziplist 編碼
主要是為了節約內存,因此所有數據都是采用線性連續的內存結構。ziplist 編碼是應用范圍最廣的一種,可以分別作為hash/ list / zset /類型的底層數據結構實現。首先從ziplist 編碼結構開始分析,它的內部結構類似這樣,
ziplist結構字段含義:
1. zlbytes: 記錄整個壓縮列表所占字節長度,方便重新調整ziplist空間。類型是int-32 ,長度是4字節。
2. zltail:記錄距離尾節點的偏移量,方便尾節點彈出操作。類型是int-32,長度為4字節。
3. zllen: 記錄壓縮 鏈表節點數量,當長度超過2^16-2時需要遍歷整個列表獲取長度,一般很少見。類型是Int-16,長度是2字節。
4. entry: 記錄具體的節點,長度根據實際存儲的數據而定。
?a.prev_entry>bytes_length: 記錄前一個節點 所占空間,用于快速定位上一個節點,可實現列表反向迭代。
b.encoding: 標示當前節點編碼和長度,前兩位標示編碼類型: 字符串/整數? 其余位標示數據長度。
c contents:保存 節點的值,針對實際數據長度做內存占用優化。
5.zlend: 記錄列表結尾,占用一個字節。
根據以上特點總結出該數據類型特點如下:
內部表現為數據緊湊排列的一塊連續內存數組
可以模擬雙向鏈表結構,以O(1)時間復雜度入隊和出隊
新增刪除操作涉及內存重新分配或釋放,加大了操作的復雜性
讀寫操作涉及復雜的指針移動,最壞時間復雜度是O(n2)
適合存儲小對象和長度有限的數據
?
總結
以上是生活随笔為你收集整理的Redis开发与运维之第八章理解内存(四)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VI-ORB环境配置
- 下一篇: MFC编程入门之十三(对话框:属性页对话