本文首發於公眾號:Hunter後端 原文鏈接:Redis數據結構一之對象的介紹及各版本對應實現 本篇筆記開始介紹 Redis 數據結構的底層實現。 當我們被問到 Redis 中有什麼數據結構,或者說數據類型,我們可能會說有字元串、列表、哈希、集合、有序集合。 其實這幾種數據類型在 Redis 中都由 ...
本文首發於公眾號:Hunter後端
原文鏈接:Redis數據結構一之對象的介紹及各版本對應實現
本篇筆記開始介紹 Redis 數據結構的底層實現。
當我們被問到 Redis 中有什麼數據結構,或者說數據類型,我們可能會說有字元串、列表、哈希、集合、有序集合。
其實這幾種數據類型在 Redis 中都由對象構成,而且是兩個對象,一個鍵對象,一個值對象。
在這些數據類型中,它們的鍵都是字元串對象,而值可以是前面說的字元串對象、列表對象、哈希對象、集合對象、有序集合對象中的一種,這個取決於鍵值對的數據類型。
而在 Redis 中,這些對象都有其更底層的實現方式,也就是說這一篇筆記我們要介紹的,更底層的數據結構,而且不同的 Redis 版本有不一樣的數據結構,最基礎的數據結構包括簡單動態字元串、字典、跳躍表、整數集合等,
接下來我們先介紹一下 Redis 中對象的構成,然後介紹一下不同 Redis 版本中每個對象所使用的的底層數據結構,之後再逐個介紹這些數據結構的實現原理,以下是本篇筆記的目錄:
- Redis 對象的介紹
- 不同版本的 Redis 對象的數據結構
註意:本篇文章的主體框架內容是基於書籍《Redis設計與實現》進行描述的,部分過時內容都基於網上查詢的相應資料與最新版本進行了對齊,如有其他疏漏,還望指正。
1、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 則是作為指針指向的是對象的底層數據結構地址。
上面這些查看對象底層編碼的命令,我們會在介紹完各個底層數據結構之後根據存儲的不同數據類型進行使用。
2、不同版本的 Redis 對象的數據結構
Redis 3.2 版本以前
在 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 | 跳躍表 |
Redis 3.2 版本
而在 3.2 版本,主要對列表對象的底層實現做了修改,由 quicklist 構成底層實現,quicklist 實際上是 linkedlist 和 ziplist 的混合結構。
列表對象
編碼(OBJECT ENCODING輸出結果) | 底層數據結構 |
---|---|
quicklist | 快速列表 |
Redis 5.1 之後版本
在 Redis 5.1 版本,引入了新的數據結構 listpack,6.x 版本作為過渡階段,並且在 7.0 版本,listpack 已經完全替換了 ziplist,成為了哈希對象、有序集合對象的底層數據結構的原有實現之一,更改如下:
哈希對象
編碼(OBJECT ENCODING輸出結果) | 底層數據結構 |
---|---|
listpack | listpack |
hashtable | 字典 |
有序集合對象
編碼(OBJECT ENCODING輸出結果) | 底層數據結構 |
---|---|
listpack | listpack |
skiplist | 跳躍表 |
而且 quicklist 也變成了 linkedlist 和 listpack 的混合結構
這一篇筆記只是作為一個引子,引入 Redis 中各個數據結構的底層結構,在下一篇筆記中我們將正式逐個介紹各個數據結構的底層實現。
如果想獲取更多後端相關文章,可掃碼關註閱讀: