1.3 zipmap 結構
如果redisObject的type 成員值是 REDIS_HASH 類型的,則當該hash 的 entry 小於配置值: hash-max-zipmap-entries 或者value字串的長度小於 hash-max-zipmap-value, 則可以編碼成 REDIS_ENCODING_ZIPMAP 類型儲存,以節約記憶體. 否則採用 Dict 來儲存.
zipmap 其實質是用一個字串數組來依次儲存key和value,查詢時是依次遍列每個 key-value 對,直到查到為止. 其結構如下:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131229/210143C28-0.jpg" style="border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;text-align:center;background-color:#f3f3f3;padding:4px 5px 5px;margin:10px;" alt="Image011730.jpg" />
為了節約記憶體,這裡使用了一些小技巧來儲存 key 和 value 的長度. 如果 key 或 value 的長度小於ZIPMAP_BIGLEN(254),則用一個位元組來表示,如果大於ZIPMAP_BIGLEN(254),則用5個位元組儲存,第一個位元組為儲存ZIPMAP_BIGLEN(254),後面4個位元組儲存 key或value 的長度.
初始化時只有2個位元組,第1個位元組表示 zipmap 儲存的 key-value 對的個數(如果key-value 對的個數超過 254,則一直用254來表示, zipmap 中實際儲存的 key-value 對個數可以通過 zipmapLen() Function Compute得到).
-
hset(nick,wuzhu) 後,
第1個位元組儲存key-value 對(即 zipmap 的entry 數量)的數量1
第2個位元組儲存key_len 值 4
第3~6 儲存 key “nick”
第 7 位元組儲存 value_len 值 5
第 8 位元組儲存空閉的位元組數 0 (當 該 key 的值被重設時,其新值的長度與舊值的長度不一定相等,如果新值長度比舊值的長度大,則 realloc 擴大記憶體; 如果新值長度比舊值的長度小,且相差大於 4 bytes ,則 realloc 縮小記憶體,如果相差小於 4,則將值往前移,並用 empty_len 儲存閒置byte 數)
第 9~13位元組儲存 value 值 “wuzhu”
hset(age,30)
插入 key-value 對 (“age”,30)
hset(nick,tide)
插入 key-value 對 (“nick”,”tide”), 後可以看到 empty_len 為1 ,
1.4 ziplist 結構
如果redisObject的type 成員值是 REDIS_LIST 類型的,則當該list 的 elem數小於配置值: hash-max-ziplist-entries 或者elem_value字串的長度小於 hash-max-ziplist-value, 則可以編碼成 REDIS_ENCODING_ZIPLIST 類型儲存,以節約記憶體. 否則採用 Dict 來儲存.
ziplist 其實質是用一個字串數組形式的雙向鏈表. 其結構如下:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131229/2101434Z2-1.jpg" style="border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;text-align:center;background-color:#f3f3f3;padding:4px 5px 5px;margin:10px;" alt="Image011740.jpg" />
ziplist header由3個欄位組成:
ziplist_bytes: 用一個uint32_t 來儲存, 構成 ziplist 的字串數組的總長度,包括 ziplist header,
ziplist_tail_offset: 用一個uint32_t 來儲存,記錄 ziplist 的尾部位移位置.
ziplist_length: 用一個 uint16_t 來儲存,記錄 ziplist 中 elem 的個數
ziplist node 也由 3 部分組成:
prevrawlen: 儲存上一個 ziplist node 的佔用的位元組數,包括: 儲存prevarwlen,currawlen 的位元組數和elem value 的位元組數.
currawlen&encoding: 當前elem value 的raw 形式存款所需的位元組數及在ziplist 中儲存時的編碼方式(例如,值可以轉換成整數,如中的”1024”, raw_len 是 4 位元組,但在 ziplist 儲存時轉換成 uint16_t 來儲存,佔2 個位元組).
(編碼後的)value
可以通過 prevrawlen 和 currawlen&encoding 來遍列 ziplist.
ziplist 還能到一些小技巧來節約記憶體.
len 的儲存: 如果 len 小於 ZIP_BIGLEN(254),則用一個位元組來儲存; 否則需要 5 個位元組來儲存,第 1 個位元組存 ZIP_BIGLEN,作為標識符.
value 的儲存: 如果 value 是數字類型的,則根據其值的範圍轉換成 ZIP_INT_16B, ZIP_INT_32B或ZIP_INT_64B 來儲存,否則用 raw 形式儲存.
1.5 adlist 結構
typedef struct listNode{struct listNode *prev;struct listNode *next;void *value;} listNode;typedef struct listIter{listNode *next;int direction;} listIter;typedef struct list{listNode *head;listNode *tail;void *(*dup)(void *ptr);void (*free)(void *ptr);int (*match)(void *ptr, void *key);unsigned int len;} list;
常見的雙向鏈表,不作分析.
1.6 intset 結構
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131229/21014342N-2.jpg" style="border-top-width:1px;border-right-width:1px;border-bottom-width:1px;border-left-width:1px;border-top-style:solid;border-right-style:solid;border-bottom-style:solid;border-left-style:solid;text-align:center;background-color:#f3f3f3;padding:4px 5px 5px;margin:10px;" alt="Image011750.jpg" />
intset 是用一個有序的整數數組來實現集合(set). struct intset 的定義如下:
typedef struct intset{uint32_t encoding;uint32_t length;int8_t contents[];} intset;
encoding: 來標識數組是 int16_t 類型, int32_t 類型還是 int64_t 類型的數組. 至於怎麼先擇是那種類型的數組,是根據其儲存的值的取值範圍來決定的,初始化時是 int16_t, 根據 set 中的最大值在 [INT16_MIN, INT16_MAX] , [INT32_MIN, INT32_MAX], [INT64_MIN, INT64_MAX]的那個取值範圍來動態確定整個數組的類型. 例如set一開始是 int16_t 類型,當一個取值範圍在 [INT32_MIN, INT32_MAX]的值加入到 set 時,則將儲存 set 的數組升級成 int32_t 的數組.
length: 表示 set 中值的個數
contents: 指向整數數組的指標
本文出自 “螞蟻窩” 部落格,請務必保留此出處http://feihan21.blog.51cto.com/1364153/1300020