Redis內部資料結構實現解析

2021-07-05 21:22:37 字數 2305 閱讀 4633

redis目前在key-value儲存以及快取系統中有著非常廣泛的應用,且以高效快速著稱。不同於其他key-value資料庫,redis提供了豐富的資料結構型別,value可以是字串、列表、雜湊和有序集等,為使用者操作帶來了極大的便利。本文希望通過分析其內部資料結構及演算法的實現機制,來揭示其高效能的背後的原因。

由於所有的key都是字串,字串在redis中的應用非常廣泛。redis底層使用sds(****** dynamic string)表示簡單字串,從而替代c語言中的char *型別,以支援高效的字串擴充套件操作。

sds的實現方式如下,其中sds是char *的別名。當新增乙個value為字串型別的鍵值對時,redis將value儲存在乙個adshdr例項中,buf儲存value的實際資料,為buf分配的空間長度與value當前所佔空間相同,即len為value的長度(包括字串末尾的』\0』),free為0。在建立adshdr例項完成後,函式將指向buf的指標返回給sds,以便於管理adshdr結構體例項的增、刪、改、查等操作。

typedef char *sds;

struct sdshdr ;

redis的字典(dictionary)的底層實現利用的是hash表。字典的結構體如下:

typedef struct dict  dict;
雜湊表的結構如下:

typedef struct dictht  dictht;
雜湊表中的每乙個元素指向乙個表結點,即dictentry結構體例項的指標,每個dictentry由乙個鍵值對和乙個指向後繼表節點的指標next構成,從而可以使用鏈位址法處理雜湊衝突。

(圖來自《redis記憶體儲存結構分析》)

乙個字典例項中有兩個hash表,當在空字典中新增第一條資料時,redis會為ht[0]所指向的table分配一定的儲存空間;隨著資料量的逐漸增多,字典的索引利用率達到一定比例時,需要對字典進行rehash的操作,從而保證字典的查詢和插入效率保持在較高的水準,即字典的expend。這時,會建立乙個更大的table(空間至少為ht[0]的兩倍),其位址被賦給ht[1],字典中的資料將由ht[0]遷移到ht[1]。

在遷移過程開始時,rehashidx值設定為0,標誌著字典處於遷移狀態;遷移結束後,ht[0]的資料將被清空,並將ht[1]更改為新的ht[0],ht[1]指向乙個新的空hash表,rehashidx的值重新設為-1,標誌著字典不在資料遷移狀態中。

如果table中的資料量比較大,就會出現遷移時間過長的問題,致使在乙個相對較長的時間段內,使用者無法進行其他操作。因此在實際中,資料遷移是分階段完成的,rehashidx會記錄rehash進行到ht[0]的哪個索引位置上。在遷移過程中,若對字典進行新增操作,則新的節點將會新增到ht[1]中;若對字典進行刪除或查詢操作,則需要在ht[0]和ht[1]上同時進行。

由於hash表中資料量是動態變化的,當索引的利用率較低時,也可以通過rehash進行字典收縮(shrink)操作,即用乙個將資料遷移到乙個更小的table中。不同的是,字典的expend操作是自動觸發的,而shrink是通過程式呼叫執行的。

跳躍表是一種隨機化資料結構,基於併聯的列表,其插入、查詢、刪除的時間複雜度均為log(n),可與二叉樹相媲美。跳躍表主要由表頭、節點和表尾組成,其節點分布在多層鍊錶中。

跳躍表由結構體zskiplist定義:

typedef struct zskiplist  zskiplist;
表的節點由zskiplistnode定義,每個節點中存有乙個score-member指針對,score為跳躍表的索引,*obj指向儲存值member的域。

typedef struct zskiplistnode  level;

} zskiplistnode;

跳躍表在redis中應用的結構示意圖如下:

(圖來自 《redis設計與實現》)

跳躍表在redis中主要用作有序集型別的底層資料結構,通過層層遍歷查詢與給定score值相一致的節點,從而獲取member的值。跳躍表編碼的有序集由乙個dictionary和skiplist構成。首先通過dictionary查詢出score的值,然後再根據score值在skiplist查取想要獲得的value。

redis內部資料結構的資料結構

redis對外的公眾的資料結構有五種string,list,set,hash,zset 編碼常量 編碼所對應的底層資料結構 redis encoding int long 型別的整數 redis encoding embstr embstr 編碼的簡單動態字串 redis encoding raw ...

Redis基礎資料結構內部實現簡單介紹

5種基礎資料結構 string 字串 set age 30 incr age 自增list 列表 右近左出 佇列 右邊進右邊出 棧 警惕慢操作ltrim key start index end index 刪除start index到 end index以外的所有元素內部儲存 快速列表 hash 字...

Redis學習筆記 Redis內部資料結構

redis內部資料結構 redis和其他key value資料庫的很大區別是它支援非字串型別的value值。它支援的value值的型別如下 sds dynamic string 簡單動態字串 雙端鍊錶 字典 dictionary map associative array 跳躍表 skiplist ...