壓縮列表是為了節省記憶體而開發的,可以包含任意多個節點(entry),每乙個節點可以儲存乙個位元組陣列或者乙個整數值。
下圖展示了壓縮列表的各個組成部分,
* ziplist 屬性巨集 */
//定位到 ziplist 的 bytes 屬性,該屬性記錄了整個 ziplist 所占用的記憶體位元組數
#define ziplist_bytes(zl) (*((uint32_t*)(zl)))
//定位到 ziplist 的 offset 屬性,該屬性記錄了到達表尾節點的偏移量
#define ziplist_tail_offset(zl) (*((uint32_t*)((zl)+sizeof(uint32_t))))
//定位到 ziplist 的 length 屬性,該屬性記錄了 ziplist 包含的節點數量
#define ziplist_length(zl) (*((uint16_t*)((zl)+sizeof(uint32_t)*2)))
//返回 ziplist 表頭的大小
#define ziplist_header_size (sizeof(uint32_t)*2+sizeof(uint16_t))
//返回指向 ziplist 第乙個節點(的起始位置)的指標
#define ziplist_entry_head(zl) ((zl)+ziplist_header_size)
//返回指向 ziplist 最後乙個節點(的起始位置)的指標
#define ziplist_entry_tail(zl) ((zl)+intrev32ifbe(ziplist_tail_offset(zl)))
//返回指向 ziplist 末端 zip_end (的起始位置)的指標
#define ziplist_entry_end(zl) ((zl)+intrev32ifbe(ziplist_bytes(zl))-1)
previous_entry_length
屬性的長度可以是1
位元組或者5
位元組:
下圖 展示了乙個壓縮列表節點,previous_entry_length
為0x05
, 表示前一節點的長度為5
位元組。
通過previous_entry_length
屬性,我們可以實現從表尾向表頭遍歷操作:
舉個例子,有乙個當前節點起始位址的指標c
, 那麼我們只要用指標c
減去當前節點previous_entry_length
屬性的值, 就可以得出乙個指向前乙個節點起始位址的指標p
。
redis對位元組陣列和整數編碼提供了一組巨集定義:
/*value成員負責根據encoding來儲存位元組陣列或整數* 字串編碼型別 */
#define zip_str_06b (0 << 6)
#define zip_str_14b (1 << 6)
#define zip_str_32b (2 << 6)
/** 整數編碼型別 */
#define zip_int_16b (0xc0 | 0<<4)
#define zip_int_32b (0xc0 | 1<<4)
#define zip_int_64b (0xc0 | 2<<4)
#define zip_int_24b (0xc0 | 3<<4)
#define zip_int_8b 0xfe
如果乙個壓縮列表中,有多個連續、長度介於250位元組到253位元組之間的節點,因此記錄這些節點只需要1個位元組的prev_entry_len,如果要插入乙個長度大於等於254的新節點到壓縮列表的頭部,然而原來的節點的prev_entry_len成員長度僅僅為1個位元組,無法儲存新節點的長度,因此會對新節點之後的所有prev_entry_len成員大小為1位元組的節點產生連鎖更新。同樣的,如果乙個壓縮列表中,是多個連續的長度大於等於254的節點,當往壓縮列表的頭部插入乙個長度小於254的節點,也會產生連鎖更新。另外刪除節點也會產生連鎖更新。
下圖展示了連鎖更新的過程:
redis原始碼剖析 skiplist
試想乙個業務場景 遊戲需要實現乙個實時更新的排行榜應該如何實現 首先想到使用有序的雙端鍊錶,因為插入的時間複雜度為o 1 但是定位的平均時間複雜度為o n 當頻繁更新排行榜的時候效率比較低 有沒有乙個結構 能夠滿足快速定位到相應的位置並插入?跳躍表就能滿足這個需求 跳躍表的思想是給資料結點建立索引 ...
redis原始碼剖析 dict
typedef struct dictentry v struct dictentry next dictentry typedef struct dicttype dicttype this is our hash table structure.every dictionary has two ...
libevent原始碼深度剖析七
事件主迴圈 張亮現在我們已經初步了解了libevent的reactor元件 event base和事件管理框架,接下來就是libevent事件處理的中心部分 事件主迴圈,根據系統提供的事件多路分發機制執行事件迴圈,對已註冊的就緒事件,呼叫註冊事件的 函式來處理事件。libevent將i o事件 定時...