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
,另一種是分別儲存在不同變數中,如 hisdshdr8
,hisdshdr16
,hisdshdr32
,hisdshdr64
在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 |