本文首發於公眾號:Hunter後端
原文連結:Redis資料結構一之物件的介紹及各版本對應實現
本篇筆記開始介紹 Redis 資料結構的底層實現。
當我們被問到 Redis 中有什麼資料結構,或者說資料型別,我們可能會說有字串、列表、雜湊、集合、有序集合。
其實這幾種資料型別在 Redis 中都由物件構成,而且是兩個物件,一個鍵物件,一個值物件。
在這些資料型別中,它們的鍵都是字串物件,而值可以是前面說的字串物件、列表物件、雜湊物件、集合物件、有序集合物件中的一種,這個取決於鍵值對的資料型別。
而在 Redis 中,這些物件都有其更底層的實現方式,也就是說這一篇筆記我們要介紹的,更底層的資料結構,而且不同的 Redis 版本有不一樣的資料結構,最基礎的資料結構包括簡單動態字串、字典、跳躍表、整數集合等,
接下來我們先介紹一下 Redis 中物件的構成,然後介紹一下不同 Redis 版本中每個物件所使用的的底層資料結構,之後再逐個介紹這些資料結構的實現原理,以下是本篇筆記的目錄:
注意:本篇文章的主體框架內容是基於書籍《Redis設計與實現》進行描述的,部分過時內容都基於網上查詢的相應資料與最新版本進行了對齊,如有其他疏漏,還望指正。
舉一個例子,當我們設定一個字串型別的資料:
set msg "hello world"
這樣,我們就建立了兩個物件,且兩個都是字串物件,因為鍵值對的 key 和 value 都是字串。
如果我們建立了一個列表資料,那麼 key 是字串物件,而值 value 是列表物件。
在 Redis 中,每個物件都由一個 redisObject 結構來表示:
typedef struct redisObject{
//型別
unsigned type:4;
//編碼
unsigned encoding:4;
//指向底層實現資料結構的指標
void *ptr
//...
} robj;
type
在上面的結構中,type 指的是這個物件的型別,比如我們建立了一個列表資料,那麼這個資料的 key 就是一個字串物件,由這個結構裡的 type 來指定,這個資料的 value 就是一個列表物件,也是由 type 來進行指定區分。
但是,當我們想要知道一條資料的資料型別是字串、列表、雜湊、集合、有序集合的哪一種時,我們常常是需要知道的這條資料的 value 的型別,一般也是指的 value 的型別,因為資料的 key 的型別總是字串物件。
一條資料的值物件型別的獲取我們可以用 TYPE 命令來操作:
TYPE msg
TYPE 型別的值輸出就是我們那五種型別:string、list、hash、set、zset
encoding
encoding 指的是這個物件底層資料結構使用的編碼。
一個物件在不同的情況下的編碼及底層資料結構可能是不一樣的,比如對於字串物件,它的編碼包括 int,embstr,raw 這三種,但後兩種的底層結構其實都是簡單動態字串(SDS),不過它們的底層使用方式略有不同,這個我們在下一節再介紹。
獲取物件的值的編碼使用 OBJECT ENCODING
命令:
OBJECT ENCODING msg
ptr
ptr 則是作為指標指向的是物件的底層資料結構地址。
上面這些檢視物件底層編碼的命令,我們會在介紹完各個底層資料結構之後根據儲存的不同資料型別進行使用。
在 Redis 3.2 版本以前,每個物件對應的編碼,及底層資料結構如下:
字串物件
編碼(OBJECT ENCODING輸出結果) | 底層資料結構 |
---|---|
int | 整數 |
embstr | embstr編碼的SDS |
raw | SDS |
列表物件
編碼(OBJECT ENCODING輸出結果) | 底層資料結構 |
---|---|
ziplist | 壓縮列表 |
linkedlist | 雙向連結串列 |
雜湊物件
編碼(OBJECT ENCODING輸出結果) | 底層資料結構 |
---|---|
ziplist | 壓縮列表 |
hashtable | 字典 |
集合物件
編碼(OBJECT ENCODING輸出結果) | 底層資料結構 |
---|---|
intset | 整數集合 |
hashtable | 字典 |
有序集合物件
編碼(OBJECT ENCODING輸出結果) | 底層資料結構 |
---|---|
ziplist | 壓縮列表 |
skiplist | 跳躍表 |
而在 3.2 版本,主要對列表物件的底層實現做了修改,由 quicklist 構成底層實現,quicklist 實際上是 linkedlist 和 ziplist 的混合結構。
列表物件
編碼(OBJECT ENCODING輸出結果) | 底層資料結構 |
---|---|
quicklist | 快速列表 |
在 Redis 5.1 版本,引入了新的資料結構 listpack,6.x 版本作為過渡階段,並且在 7.0 版本,listpack 已經完全替換了 ziplist,成為了雜湊物件、有序集合物件的底層資料結構的原有實現之一,更改如下:
雜湊物件
編碼(OBJECT ENCODING輸出結果) | 底層資料結構 |
---|---|
listpack | listpack |
hashtable | 字典 |
有序集合物件
編碼(OBJECT ENCODING輸出結果) | 底層資料結構 |
---|---|
listpack | listpack |
skiplist | 跳躍表 |
而且 quicklist 也變成了 linkedlist 和 listpack 的混合結構
這一篇筆記只是作為一個引子,引入 Redis 中各個資料結構的底層結構,在下一篇筆記中我們將正式逐個介紹各個資料結構的底層實現。
如果想獲取更多後端相關文章,可掃碼關注閱讀: