Redis 簡單動態(tài)字符(SDS)

  • 后續(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)分配,如前面lenfree各需要4字節(jié),申請16字節(jié)時,除去結(jié)束符\0的位置,剩下7字節(jié)就是buf的使用長度了,需要注意結(jié)束符\0不算到len中。
  • 以上展示了兩個版本sds結(jié)構(gòu)體代碼,V3.2之前freelen各占4字節(jié),比較浪費(fèi)空間,最節(jié)省的辦法就是按位算lenfree的個數(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ù)。

友情鏈接更多精彩內(nèi)容