目錄
- 1、背景
- 2、SDS底層實現
1、背景
redis作為高性能的內存數據庫,對字符串操作(如鍵、值的存儲)有極高的要求。c語言原生字符串(以\0結尾的字符串數據)有一些缺點:長度計算需要遍歷(O(n)時間復雜度)、頻繁內存重分配、二進制不安全、無緩沖區管理。為了解決這些問題,redis使用了SDS(Simple Dynamic String),在兼容c字符串的同時,提供了更高效、更安全的能力。
2、SDS底層實現
SDS底層結構體如下:
//redis 5+已棄用
struct __attribute__ ((__packed__)) sdshdr5 {unsigned char flags; /* 3 lsb of type, and 5 msb of string length */char buf[];
};//存儲長度范圍:0~255(2的8次方減1)
struct __attribute__ ((__packed__)) sdshdr8 {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[];
};//存儲長度范圍:256~65535(2的16次方減1)
struct __attribute__ ((__packed__)) sdshdr16 {uint16_t len; /* used */uint16_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};//存儲長度范圍:656536~(2^32-1)
struct __attribute__ ((__packed__)) sdshdr32 {uint32_t len; /* used */uint32_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};//存儲長度范圍:大于等于2^32字節
struct __attribute__ ((__packed__)) sdshdr64 {uint64_t len; /* used */uint64_t alloc; /* excluding the header and null terminator */unsigned char flags; /* 3 lsb of type, 5 unused bits */char buf[];
};
根據存儲字符串的大小使用不同的sdshdr結構,其字段含義為:
字段名 | 含義 |
---|---|
len | 字符串實際長度(已用字節數) |
alloc | 分配的總容量(不包括頭部和結尾的\0) |
flags | SDS類型 |
buf[] | 存儲實際數據 |
flags代表的宏定義如下:
#define SDS_TYPE_5 0
#define SDS_TYPE_8 1
#define SDS_TYPE_16 2
#define SDS_TYPE_32 3
#define SDS_TYPE_64 4
SDS的特性如下:
特性 | 實現原理 |
---|---|
O(1)長度獲取 | 直接讀取len字段,無需遍歷 |
二進制安全 | 通過len記錄字節數(而非依賴\0),可存儲任意二進制數據 |
內容預分配 | 擴容時按規則分配額外空間,減少重分配次數 |
惰性釋放 | 縮容時不立即釋放內存,通過alloc字段記錄剩余空間,供后續操作復用 |
兼容c字符串 | 在buf末尾自動追加\0,可直接傳遞buf給c函數 |