Redis Reading Notes

Sonui發表於2024-07-17

Redis 是一個開源的記憶體資料庫,它支援多種資料結構,如字串、列表、集合、有序集合、雜湊表等,同時支援持久化,主從複製,叢集等功能。在這篇文章中記錄了閱讀 Redis 原始碼的一些筆記。

本文原始碼版本截至commit:

14f802b: Initialize cluster owner_not_claiming_slot to avoid warning (#12391)

資料結構

SDS 動態字串實現

redis透過sds來儲存字串,相較於c語言的字串,sds有以下優點:

  • 常數複雜度獲取字串長度(對於c語言字串,需要遍歷整個字串才能獲取長度)
  • 減少修改字串時所需的記憶體重分配次數
  • 二進位制安全(可以儲存任意資料,包括空字元,如 \0

/* Note: sdshdr5 is never used, we just access the flags byte directly.
 * However is here to document the layout of type 5 SDS strings. */
struct __attribute__ ((__packed__)) hisdshdr5 {
    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
    char buf[];
};
struct __attribute__ ((__packed__)) hisdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

sds有兩種,一種是型別長度以高低位儲存在一個變數中如 hisdshdr5,另一種是分別儲存在不同變數中,如 hisdshdr8hisdshdr16hisdshdr32hisdshdr64

hisdshdr5中,flags的低三位儲存型別,高五位儲存長度,所以長度最大為32位,即2^5-1,即31位元組

在程式碼註釋中有以下說明

Note: sdshdr5 is never used, we just access the flags byte directly.
However is here to document the layout of type 5 SDS strings.

意思是說,hisdshdr5並沒有被使用,我們直接訪問flags位元組,但是這裡是為了記錄型別5的sds字串的佈局。

hisdshdr8中,len儲存長度,alloc儲存分配長度,flags儲存型別,所以長度最大為8位,即2^8-1,即255位元組

結構體中使用了__attribute__ ((__packed__)),這是gcc的擴充套件,用於告訴編譯器不要對結構體進行位元組對齊,這樣可以節省記憶體,但是會降低訪問效率,同時使用了柔性陣列成員(C99標準引入),柔性陣列成員是一種特殊的陣列型別,它可以在結構體中定義一個沒有指定大小的陣列,這樣就可以根據需要動態地分配記憶體,而不用使用指標。柔性陣列成員必須是結構體的最後一個成員,並且結構體中至少要有一個其他的命名成員。柔性陣列成員是C99標準引入的,但是一些編譯器也支援C89和C++中使用它,只是語法有些不同。柔性陣列成員的優點是可以提高記憶體分配的效率,提高資料的區域性性,以及生成更好的程式碼。

參考資料

說明 連結
Redis 官網 https://redis.io/
如何閱讀 Redis 原始碼? https://blog.huangz.me/diary/2014/how-to-read-redis-source-code.html

相關文章