Redis那些事兒 資料結構

2021-10-25 12:46:47 字數 3499 閱讀 8093

鍊錶字典

跳躍表整數集合

壓縮列表

物件redis作為一種流行的nosql資料庫,廣泛被開發者使用,由於其出色的效能(說別的沒用,快就完了),其業務覆蓋率越來越廣泛,由於其本質為kv鍵值對形式的記憶體資料庫,常見的就是用於快取系統的設計。其相對於其他nosql資料庫,redis具有很多優點,比如對持久化良好的支援、對事務的支援、具有豐富的資料型別等。對於這些表現出來的優點,離不開底層資料結構的設計支援,本文為大家介紹一些reids底層所應用的資料結構

redis中最常用的資料型別非字串莫屬,所有資料型別的key、以及業務中對字串的處理,都用到了大量字串資料結構。但是,redis的字串設計不同於原生c語言的字串,而是自己構建了一種資料結構,名為sds(****** dynamic string)的簡單動態字串。

之所以採取這種結構而不是c字串,是因為sds具有以下優點

因為len屬性記錄了字串的長度,所以獲取字串的時間複雜度僅為o(1)。

因為c字串不記錄自身長度,所以很容易造成緩衝區溢位,如果之前沒有為乙個字串分配足夠多的空間,那麼很容易造成當前字串溢位到其他空間,與c字串不同的是,sds的空間分配策略完全杜絕了發生緩衝區一處的可能性:當需要對sds進行修改時,會先檢查sds的空間是否滿足修改所需的要求,如果不滿足會先將sds擴充套件至所需大小,再執行修改。

二進位制安全

雖然sds的api都是二進位制安全的,但他們一樣遵循c字串以空字串結尾的慣例,並且總會在為buf陣列分配空間時,多分配乙個位元組來容納這個空字元,這是為了讓那些儲存文字資料的sds可以重用一部分庫定義的函式。

redis的資料庫就是使用字典來作為底層實現的,對資料庫的增刪改查也是構建在對字典的操作之上的。

雜湊表

typedef

struct dicthtdictht;

雜湊表節點

typedef

struct dictentry v;

// 指向下個雜湊表節點,形成鍊錶

struct dictentry *next;

}dictentry;

字典

節點資料結構

typedef

struct zskiplistnode level;

// 後退指標

struct zskiplistnode *backward;

// 分值

double score;

// 成員物件

robj *obj;

}zsklistnode;

跳躍表

公升級:擴充套件整數集合底層陣列的空間大小,並為新元素分配空間

將底層陣列的現有元素都轉化為與新元素相同的型別,並講型別轉化後的元素放置到正確的位置,而且放元素的過程中,需要繼續維持底層陣列的有序性質不變

將新元素加到底層陣列裡面

降級:

不支援降級,一旦公升級,編碼就會一直保持公升級後的狀態

當乙個列表只包含少量列表項,並且每個列表項要麼是小整數值,要麼是長度比較短的字串,那麼redis就會使用壓縮列表作為底層實現

另外、當乙個雜湊鍵只包含少量鍵值對,並且每個鍵值對的鍵和值要麼是小整數值,要麼是長度較短的字串,redis就會使用壓縮列表作為底層實現

redis並不是直接使用資料結構來實現鍵值對資料庫的,而是基於這些資料結構建立了乙個物件系統,包含字串物件、列表物件、雜湊物件、集合物件和有序集合物件,每種物件都用到了至少一種前面介紹的資料結構。

redis在執行命令之前,根據物件的型別來判斷乙個物件是否可以執行給定的命令,還可以根據不同的使用場景設定不同的資料結構,從而優化不同場景下的使用效率。個人覺得此設計為物件導向設計思想的多型的體現。

本文主要介紹各種物件使用到了哪些資料結構。

字串物件的編碼可以是int、raw、embstr。raw編碼即為sds結構。embstr為一種優化的編碼方式,和raw結構類似,不同的是raw需要呼叫兩次記憶體分配,而embstr只需要一次。使用條件為儲存的字串長度小於等於32位元組。

列表物件的編碼可以是ziplist或者linkedlist。ziplist編碼底層使用壓縮列表作為底層實現,linkedlist使用雙端鍊錶作為底層實現。

當列表物件同時滿足以下條件時,使用ziplist編碼:

雜湊物件編碼可以是ziplist或者hashtable。ziplist編碼的底層實現為壓縮列表,hashtable編碼的底層實現為字典。

當雜湊物件同時滿足以下條件時,雜湊物件使用ziplist編碼:

集合物件的編碼可以是intset或者hashtable,intset編碼的底層實現是整數集合,hashtable的底層實現是字典,字典的每乙個鍵都是乙個字串物件,字典的值都為null。

當集合物件同時滿足以下條件時,集合物件使用intset編碼:

有序集合物件的編碼可以是ziplist或者skiplist,ziplist使用壓縮列表作為底層實現,skiplist編碼使用zset作為底層實現,乙個zset同時包含乙個字典和乙個跳躍表。在理論上可以單獨使用字典或者跳躍表中的一種,但無論單獨使用哪乙個,在效能上對比同時使用兩個都會有所降低,用字典的話,保留了o(1)複雜度的查詢,但是字典是無序的,每次執行範圍型操作時都需要進行排序;如果只是使用跳躍表範圍型操作的有點會被保留,那麼根據成員查詢分值的操作將從o(1)上公升為o(logn)。

當有序集合物件同時滿足以下兩個條件時,物件使用ziplist編碼:

Redis資料結構

字典 dict 是redis裡最核心的資料結構,正如其全稱remote dictionary service所說,redis其實就是乙個字典服務,字典以key value的形式呈現給使用者,key是簡單的字串,而value可以是各種資料結構,比如字串 string 鍊錶 list 集合 set 排序...

Redis 資料結構

最近接觸到了redis的使用,借這個機會深入的了解一下redis的實現和設計原理。下面先介紹一下redis底層所用到的資料結構。redis的實現幾乎都是基於下面的幾個資料結構之上的。struct sdshdr struct listnode struct list struct dictentry ...

redis 資料結構

今天學習了redis的列表型別 lpush ltrim lrange lpush mylist content ltrim 0,99 lrange 0,1 lrange 兩個引數 分別代表第乙個元素和最後乙個元素 redis的列表型別,可以用來做訊息佇列 使用乙個程序 用lpush命名作為生產者 使...