【Redis】內部資料結構自頂向下梳理

數小錢錢的種花兔發表於2020-12-31

本部落格將順著自頂向下的思路梳理一下Redis的資料結構體系,從資料庫到物件體系,再到底層資料結構。我將基於我的一個專案的程式碼來進行介紹:daredis。該專案中,使用Java實現了Redis中所有的資料結構,思想與Redis大致類似,各種變數的命名與Redis原始碼基本一致,只是將結構體換成了類來實現。

Redis資料庫

Redis伺服器在初始化時,會建立一個db陣列,大小預設是16,即建立16個資料庫。如下所示:

public class RedisServer {

    private static int dbNum = 16;
    public static RedisDB[] db;

    public static void init(){
        db = new RedisDB[dbNum];
    }

    public static void initDB(int index){
        db[index] = new RedisDB();
    }
}

實際上,每個客戶端都會擁有一個目標資料庫,預設情況下為db[0]。客戶端執行命令時,目標資料庫會成為其操作物件。

RedisDB型別包含一個字典,程式碼如下:

public class RedisDB {

    //資料庫的鍵空間
    Dict<SDS, RedisObject> dict;

    public RedisDB() {
        this.dict = new Dict<>();
    }
}

資料庫RedisDB實際上包含一個Dict型別,即字典(Redis中尤為關鍵的底層資料結構),是一個鍵值對集合,鍵名是SDS字串,鍵值是RedisObject。Dict是後面要講的一種底層資料結構,在資料庫體系中也是用到了Dict。

可以這樣理解,Redis的所有物件體系都是掛在一個Dict字典下的。這也體現了Redis非關係型的特點。

Redis物件系統

繼續向下探索,看一看資料庫鍵值RedisObject是什麼。RedisObject表示Redis中的物件。Redis包含五種物件,統稱物件系統

  • RedisHash雜湊物件
  • RedisList列表物件
  • RedisSet集合物件
  • RedisString字串物件
  • RedisZSet有序集合物件

RedisObject包含一個型別欄位type和一個編碼欄位encoding,以及一個底層資料結構的引用ptr。如下所示:

public abstract class RedisObject {
    protected int type;
    protected int encoding;
    protected RedisObj ptr;
}

type的值由一個列舉型別來維護,表示上述五種型別中的某種型別,如下所示

public enum RedisType {
    STRING(0),
    LIST(1),
    HASH(2),
    SET(3),
    ZSET(4);
    private final int val;
    RedisType(int VAL) {
        this.val = VAL;
    }
    public int VAL(){
        return val;
    }
}

encoding同樣由一個列舉型別來維護,表示ptr指向的資料結構的型別,如下所示

public enum RedisEnc {
    RAW(0),
    INT(1),
    HT(2),
    LINKEDLIST(3),
    ZIPLIST(4),
    INTSET(5),
    SKIPLIST(6),
    EMBSTR(7);
    private final int val;
    RedisEnc(int VAL) {
        this.val = VAL;
    }
    public int VAL(){
        return val;
    }
}

RedisObject中的ptr引用的物件可以是多種型別。例如列表物件可由壓縮列表ziplist或者雙端連結串列linkedlist來編碼。兩種編碼可以轉換,當滿足以下兩個條件時,使用ziplist編碼

  • 列表物件儲存的所有字串元素長度都小於64位元組;
  • 列表物件儲存的元素數量小於512個;

兩個條件有一項不滿足,會將壓縮列表轉化為雙端連結串列。
其它Redis物件的資料結構編碼切換方式也與之類似。

Redis底層資料結構

底層資料結構指的是ptr指向的物件的內部結構,在Redis中,包含6種底層資料結構:

  • SDS動態字串
  • ziplist壓縮列表
  • list連結串列
  • dict字典
  • skiplist跳躍表
  • intset整數集合

熟悉Redis的同學來說,這些都是耳熟能詳的資料結構,就不一一去介紹原始碼了,專案daredis中都有具體實現。
之前寫過一篇介紹跳躍表的部落格,也可以看看:
【Redis】跳躍表原理分析與基本程式碼實現(java)

物件系統與各種底層資料結構對映關係如下:

相關文章