redis底层数据结构简述
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
redis的數(shù)據(jù)庫對象有五種,分別是字符串對象(key-value),列表對象(list),哈希對象(hash),集合對象(set),有序集合(sort?set)。
這些數(shù)據(jù)對象來自于底層數(shù)據(jù)類型的實現(xiàn),這些數(shù)據(jù)類型分別為簡單動態(tài)字符串,鏈表,字典,跳躍表,整數(shù)集合,壓縮列表,對象。
以下是redisObject和底層數(shù)據(jù)結構的關系
簡單動態(tài)字符串(SDS)
redis的鍵(KEY)由簡單動態(tài)字符串實現(xiàn),字符串對象(key-value)也是由簡單動態(tài)字符串實現(xiàn)的。而簡單動態(tài)字符串是由C實現(xiàn)的,它的結構如下
struct sdshr{//記錄buf中已經(jīng)使用的字節(jié)數(shù)量unsigned int len;//記錄buf中未使用的字節(jié)數(shù)量unsigned int free;//字節(jié)數(shù)組,存儲字符串char buf[]; }在redis3.2版本后,SDS的結構發(fā)生了變化,有多種數(shù)據(jù)結構,根據(jù)情況使用
//字符串長度小于32 Byte struct __attribute__ ((__packed__)) sdshdr5 {unsigned char flags; /* 記錄當前字節(jié)數(shù)組的屬性,到底是哪個SDS結構 */char buf[];/* 保存字符串真正的值 */ }; //字符串長度小于256 Byte,大于32 Byte struct __attribute__ ((__packed__)) sdshdr8 {uint8_t len; /* 記錄當前數(shù)組的長度 */uint8_t alloc; /* 記錄了當前字節(jié)數(shù)組總共分配的內存大小 */unsigned char flags; /* 記錄當前字節(jié)數(shù)組的屬性,到底是哪個SDS結構 */char buf[];/* 保存字符串真正的值 */ }; //字符串長度小于65536 Byte (64KB),大于256 Byte struct __attribute__ ((__packed__)) sdshdr16 {uint16_t len; /* 記錄當前數(shù)組的長度 */uint16_t alloc; /* 記錄了當前字節(jié)數(shù)組總共分配的內存大小 */unsigned char flags; /* 記錄當前字節(jié)數(shù)組的屬性,到底是哪個SDS結構 */char buf[];/* 保存字符串真正的值 */ }; //字符串長度小于4294967296 Byte (4GB),大于65536 Byte struct __attribute__ ((__packed__)) sdshdr32 {uint32_t len; /* 記錄當前數(shù)組的長度 */uint32_t alloc; /* 記錄了當前字節(jié)數(shù)組總共分配的內存大小 */unsigned char flags; /* 記錄當前字節(jié)數(shù)組的屬性,到底是哪個SDS結構 */char buf[];/* 保存字符串真正的值 */ }; //字符串長度大于4294967296 Byte (4GB) struct __attribute__ ((__packed__)) sdshdr64 {uint64_t len; /* 記錄當前數(shù)組的長度 */uint64_t alloc; /* 記錄了當前字節(jié)數(shù)組總共分配的內存大小 */unsigned char flags; /* 記錄當前字節(jié)數(shù)組的屬性,到底是哪個SDS結構 */char buf[];/* 保存字符串真正的值 */ };鏈表
鏈表是redis對象列表(list)的一種實現(xiàn)。當列表中元素數(shù)量比較多,或元素中字符串數(shù)量比較大時,就會使用鏈表結構。鏈表方便順序查詢,同時也方便插入和刪除。
鏈表由listNode和list組成,其結構如下
typedef struct listNode{struct listNode *prev;//前一個節(jié)點struct listNode * next;//后一個節(jié)點void * value;//節(jié)點值 } typedef struct list{//頭節(jié)點listNode * head;//尾節(jié)點listNode * tail;//長度unsigned long len;//復制函數(shù)void *(*dup) (void *ptr);//釋放函數(shù)void (*free) (void *ptr);//對比函數(shù)int (*match)(void *ptr, void *key); }結構圖如下:
字典
字典可以用來保存鍵值對,字典的結構和java的hashMap結構相似,采用hash算法保存key。字典由字典,哈希表,哈希表節(jié)點實現(xiàn)。其結構如下:
/** 哈希表節(jié)點*/ typedef struct dictEntry {// 鍵void *key;// 值,可以是三種形式:指針,8字節(jié)字符,8字節(jié)整數(shù)union {void *val;uint64_t u64;int64_t s64;} v;//指向下個哈希表節(jié)點,形成鏈表(如下hash沖突,會形成鏈表)struct dictEntry *next; } /** 哈希表*/ typedef struct dictht {// 哈希表數(shù)組// 里面存儲dictEntrydictEntry **table;// 哈希表大小unsigned long size;// 哈希表大小掩碼,用于計算索引值// 總是等于 size - 1,index = hash & sizemask// 這樣所有計算得出的hash值都可以對應于table的索引unsigned long sizemask;// 該哈希表已有節(jié)點的數(shù)量unsigned long used; } /** 字典*/ typedef struct dict {// 類型特定函數(shù),type和privdata是為了多態(tài)字典所設置的dictType *type;// 私有數(shù)據(jù)void *privdata;// 哈希表,每個字典包含兩個table// ht[0]是平時使用的哈希表,ht[1]是rehash時使用的哈希表dictht ht[2];// rehash 索引標識// 當 rehash 不在進行時,值為 -1int rehashidx; }字典結構圖如下:
跳躍表
跳躍表是一種有序的數(shù)據(jù)結構,它通過score進行排序。跳躍表有層級的概念,每個跳躍表節(jié)點有多層,每個層級會按順序指向之后若干節(jié)點的對應層級。這是為了便于查詢,通過層級查詢節(jié)點,會比按score順序依次查詢要快很多。節(jié)點和鏈表的結構如下:
typedef struct zskiplistNode{//層struct zskiplistLevel{//前進指針struct zskiplistNode *forward;//跨度unsigned int span;} level[];//后退指針struct zskiplistNode *backward;//分值double score;//成員對象robj *obj; } typedef struct zskiplist {//表頭節(jié)點和表尾節(jié)點struct zskiplistNode *header,*tail;//表中節(jié)點數(shù)量unsigned long length;//表中層數(shù)最大的節(jié)點的層數(shù)int level; }結構圖如下:
整數(shù)集合
當一個集合的元素數(shù)量不大,且類型都為整數(shù)時,redis就會使用整數(shù)集合進行存儲。它的結構如下:
typedef struct intset{//編碼方式uint32_t enconding;// 集合包含的元素數(shù)量uint32_t length;//保存元素的數(shù)組 int8_t contents[]; }壓縮列表
壓縮列表是列表對象和哈希對象的實現(xiàn)方式之一。當一個列表的元素數(shù)量不多,且值為整數(shù)和不長的字符串,這時redis會使用壓縮列表。同樣如果一個哈希對象的key和value的值數(shù)量不多,且為整數(shù)和不長的字符串時,redis也會使用壓縮列表
?
參考資料:
https://www.cnblogs.com/jaycekon/p/6227442.html
https://www.cnblogs.com/jaycekon/p/6277653.html
轉載于:https://my.oschina.net/u/241670/blog/3058326
總結
以上是生活随笔為你收集整理的redis底层数据结构简述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kibana 创建索引 POST 403
- 下一篇: 错了