實現動態表頭 Redis的設計於實現(1)

2021-10-16 01:34:46 字數 4459 閱讀 9703

redis的預設字串型別為sds。只會使用c字串作為字面量(比如列印)。

struct sdshdr ;
sds遵循c字串以空字串結尾的慣例,儲存空字串的1位元組空間不計入sds的len屬性裡面。

優點:字串的複雜度為o(1);len可直接返回長度。

杜絕緩衝區溢位;sds的空間分配杜絕了溢位可能。

減少字串修改帶來的記憶體重分配次數;修改後sds長度小於1m,分配和len同樣大小的未使用空間;修改後大於1m,則每次分配1m空間。

二進位制安全,可儲存二進位制資料;包含空字串的特殊文字格式,會使c字串誤認為結束,是二進位制不安全的。

相容c字串函式;可復用c字串函式庫。

c語言沒有鍊錶的資料結構。redis自己構建了鍊錶的實現。

//鍊錶節點

typrdef struct listnode listnode;

//鍊錶

typrdef struct list ;//節點值複製函式

void (*free) ;//節點值釋放函式

int (*match) ;//節點值對比函式

} list;

特性:雙端;鍊錶節點帶有prev和next指標,獲取前後節點的複雜度為o(1)。

無環;表頭節點的prev和表尾節點的next都指向null。

帶表頭指標和表尾指標。

帶鍊錶長度計數器。

多型;通過三個函式,可用於儲存各種不同型別的值。

c語言沒有字典的資料結構。redis自己構建了字典的實現。、

redis的資料庫就是用字典來實現的,也是雜湊建的底層實現。

//雜湊表

typrdef struct dictht dictht;

//雜湊節點

typrdef struct dictentry v;//值

struct dictentry *next;//指向下個雜湊節點,形成鍊錶

} dictentry;

//字典

typrdef struct dict dict;

typrdef struct dicttype ;//計算雜湊的函式

void *(*keydup);//複製鍵的函式

void *(*valdup);//複製值的函式

void *(*keycompare);//對比鍵的函式

void *(*keydestructor);//銷毀鍵的函式

void *(*keydestructor);//銷毀值的函式

} dicttype;

rehash:為ht[1]分配空間,讓字典同時持有ht[0]和ht[1]兩個雜湊表。在字典中維持乙個rehashidx,值為0.每次對字典的操作,先在ht[0]上執行然後rehash到ht[1],rehashidx值增加一。隨著時間的推移,ht[0]終將全部rehash到ht[1]中。這時將rehashidx置為-1。所有新增加的鍵值都會儲存到ht[1]中

跳躍表是一種有序的資料結構,支援平均o(logn)和最壞o(n)的複雜度;大部分情況下跳躍表的效率和平衡樹相媲美。

redis使用跳躍表作為有序集合鍵的底層實現。

//跳躍表節點

typrdef struct zskiplistnode level;

struct zskiplistnode *backward;//後退指標

double score;//分值

robj *obj;//成員物件

} zskiplistnode;

//跳躍表(層高為1-32的隨機數)

typrdef struct zskiplist zskiplist;

整數集合(inset)是集合鍵的底層實現之一,當乙個集合只包含整數值元素,且元素數量不多時,redis就會使用整數集合作為集合鍵的底層實現。

//整數集合

typrdef struct inset inset;

公升級:當將乙個新元素新增到整數集合裡面,且比集合現有的元素型別都要長時,需要對集合先進行公升級,然後再新增元素。(不支援降級,公升級後會保持公升級後資料型別)

1.根據新元素的型別擴充套件空間

2.將現有元素型別轉換為新型別,並將現有元素放置到新位置上

3.新增新元素到底層陣列

壓縮列表(ziplist)是列表鍵和雜湊鍵的底層實現之一。當包含少量列表項,且每個列表項是比較小的字串時,redis就使用壓縮列表來做列表鍵的底層實現。

壓縮列表:

整個壓縮列表占用大小

起始到結尾節點的位元組數

節點數量

節點1節點2

標記結尾

zlbytes

zltail

zllen

entry1

entry2

zlend

節點:前一節點的長度(長度小於254位元組,值的長度為1位元組.長度大於等於254,值的長度為5位元組)

記錄content儲存資料的型別和長度

值previous_entry_length

encoding

content

連鎖更新:previous_entry_length欄位的長度有1位元組和5位元組,若連續多個節點的長度為253,若其中乙個節點的長度更新為254,則下一節點的previous_entry_length要重1位元組變為5位元組。引起連鎖更新。

redis並沒有直接使用上面的資料結構來實現鍵值的資料庫,而是基於這些資料結構建立乙個物件系統。包含字串物件、列表物件、雜湊物件、集合物件和有序集合物件這五種型別的物件

//物件

typrdef struct redisobject robj;

型別:型別

type值

type命令輸出

字串redis_string

"string"

列表redis_list

"list"

雜湊redis_hash

"hash"

集合redis_set

"set"

有序集合

redis_zset

"zset"

編碼:編碼值對應的資料結構

redis_encoding_int

long型別的整數

redis_encoding_enbstr

embstr編碼的簡單動態字串

redis_encoding_raw

簡單動態字串

redis_encoding_ht

字典redis_encoding_linkedlist

雙向鍊錶

redis_encoding_ziplist

壓縮列表

redis_encoding_intset

整數集合

redis_encoding_skiplist

跳躍表和字典

不同的組合:

型別編碼

物件redis_string

redis_encoding_int

整數值字串

redis_string

redis_encoding_embstr

embstr編碼的簡單動態字串

redis_string

redis_encoding_raw

簡單動態字串

redis_list

redis_encoding_ziplist

壓縮列表實現的列表物件

redis_list

redis_encoding_linkedlist

雙向鍊錶實現的列表物件

redis_hsha

redis_encoding_ziplist

壓縮列表實現的雜湊物件

redis_hsha

redis_encoding_ht

字典實現的雜湊物件

redis_set

redis_encoding_intset

整數集合實現的集合物件

redis_set

redis_encoding_ht

字典實現的集合物件

redis_set

redis_encoding_ziplist

壓縮列表實現的有序集合物件

redis_set

redis_encoding_skiplist

跳躍表和字典實現的有序集合物件

為什麼有序集合要使用跳躍表和字典實現?

字典優點:以o(1)的複雜度查詢成員

跳躍表優點:範圍型操作需排序,而跳躍表是按排序儲存元素的

#可通過下面命令檢視編碼型別

object encoding key值

Redis設計於實現(二)

簡介 字典實現 字典的實現是以雜湊表作為它的底層實現,乙個雜湊表可以有多個雜湊表節點,每個節點儲存了字典中的乙個鍵值對。1.雜湊表節點 key就是鍵,v就是鍵中的值 可以是指標,unit64 t 整數,int64 t s64整數 next是將另外乙個雜湊值相同的鍵值對連線在一起的指標 為了解決衝突 ...

Redis設計於實現之字典

簡介 字典實現 字典的實現是以雜湊表作為它的底層實現,乙個雜湊表可以有多個雜湊表節點,每個節點儲存了字典中的乙個鍵值對。1.雜湊表節點 key就是鍵,v就是鍵中的值 可以是指標,unit64 t 整數,int64 t s64整數 next是將另外乙個雜湊值相同的鍵值對連線在一起的指標 為了解決衝突 ...

element ui實現複雜動態表頭

製作乙個不同省份不同業務的的統計報表。如下圖 動態表頭只需要在中v for迴圈即可,但是在多層迴圈中,prop屬性的賦值卻讓我試了半天,希望能幫到有需要的小夥伴,最終 如下 data datalist width 1200 show summary summary method getsummari...