- 后續(xù)所有未標(biāo)注版本的Redis源碼都源于5.0
簡單動態(tài)字符串SDS
- Redis里的字符串默認(rèn)為sds類型,例如所有的key就都是sds。
SDS的定義
// V3.2之前
struct sds {
// 記錄 buf 數(shù)組中未使用字節(jié)的數(shù)量
int free;
// 記錄 buf 數(shù)組中已使用字節(jié)的數(shù)量
int len;
// 字節(jié)數(shù)組,用于保存字符串
char buf[];
};
// V3.2之后,sdshdr16/sdshdr32同理
struct __attribute__ ((__packed__)) sdshdr5 {
unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
char buf[];
};
struct __attribute__ ((__packed__)) sdshdr8 {
uint8_t len; /* 已使用 */
uint8_t alloc; /* 總長 */
unsigned char flags; /* 3 lsb of type, 5 unused bits */
char buf[];
};
- sds用到了柔性數(shù)組,數(shù)組放在結(jié)構(gòu)體最后時,可以根據(jù)需要動態(tài)分配,如前面
len和free各需要4字節(jié),申請16字節(jié)時,除去結(jié)束符\0的位置,剩下7字節(jié)就是buf的使用長度了,需要注意結(jié)束符\0不算到len中。
- 以上展示了兩個版本sds結(jié)構(gòu)體代碼,V3.2之前
free和len各占4字節(jié),比較浪費(fèi)空間,最節(jié)省的辦法就是按位算len和free的個數(shù),進(jìn)而出現(xiàn)了sdshdr5、sdshdr8、sdshdr16、sdshdr32、sdshdr64。
- 新版sds中,
flags低3位就代表了sdshdrN中的某一個,3位就可以區(qū)分出5種結(jié)構(gòu),可以發(fā)現(xiàn)sdshdr5中沒有len、alloc,由flags高5位表示len,sdshdr8 sdshdr16 sdshdr32 sdshdr64就比較容易理解了,flags低3位和sdshdr5一樣,高5位是空閑狀態(tài)。
SDS與C字符串的區(qū)別
- 性能優(yōu)化:記錄后獲取字符長度時,時間復(fù)雜度降到O(1),避免遍歷。
- 函數(shù)庫兼容:SDS遵循C的慣例,結(jié)尾以'\0'結(jié)束,這樣很多C的函數(shù)庫避免重復(fù)。
- 保證安全:有l(wèi)en字段不用依賴“/0”終止符,保證二進(jìn)制安全。
SDS拼接時擴(kuò)容策略
- sds有空余空間時直接擴(kuò)容即可??臻g不足時分兩種情況,
擴(kuò)容后總長小于1M時按兩倍擴(kuò)容,大于1M時按總長+1M擴(kuò)容,最后根據(jù)長度重新選擇結(jié)構(gòu)sdshdrN并選擇是否重新開辟空間。
- 在《Redis運(yùn)維與開發(fā)》中也提到,盡量減少sds的拼接操作,避免預(yù)分配造成空間浪費(fèi)。
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。