Redis數(shù)據(jù)結(jié)構(gòu)之String

Redis使用自己的簡單動態(tài)字符串(simple dynamic string, SDS)的抽象類型。Redis中,默認以SDS作為自己的字符串表示。

struct sdshdr {    
  // 用于記錄buf數(shù)組中使用的字節(jié)的數(shù)目
  // 和SDS存儲的字符串的長度相等  
    int len;    
  // 用于記錄buf數(shù)組中沒有使用的字節(jié)的數(shù)目   
    int free;    
  // 字節(jié)數(shù)組,用于儲存字符串
    char buf[];   //buf的大小等于len+free+1,其中多余的1個字節(jié)是用來存儲’\0’的。
};

image.png

SDS除了用來保存數(shù)據(jù)庫中的字符串之外,SDS還被用作緩沖區(qū)(buffer),如AOF模塊中的AOF緩沖區(qū),以及客戶端狀態(tài)中的輸入緩沖區(qū)

使用SDS而不使用c語言的string的好處:

1、常數(shù)復雜度獲取字符串長度

C語言中:字符串只是簡單的字符的數(shù)組,當使用strlen獲取字符串長度的時候,內(nèi)部其實是直接順序遍歷數(shù)組的內(nèi)容,找到對應的’\0’對應的字符,從而計算出字符串的長度。即O(N)。

SDS:只需要訪問SDS的len屬性就能得到字符串的長度,復雜度為O(1)。

2、杜絕緩沖區(qū)溢出

Redis是C語言編寫的,并沒有方便的數(shù)據(jù)類型來進行內(nèi)存的分配和釋放(C++ STL String),必須手動進行內(nèi)存分配和釋放。

對于字符串的拼接、復制等操作,C語言開發(fā)者必須確保目標字符串的空間足夠大,不然就會出現(xiàn)溢出的情況。

當使用SDS的API對字符串進行修改的時候,

API內(nèi)部第一步會檢測字符串的大小是否滿足。
如果空間已經(jīng)滿足要求,那么就像C語言一樣操作即可。如果不滿足,則拓展buf的空間
之后再進行操作。每次操作之后,len和free的值會做相應的修改。
擴展buf空間策略:
修改之后總長度len<1MB: 總空間為2*len+1;
修改之后總長度len>=1MB: 總空間為len+1MB+1。
換句話說,預分配的空間上限是1MB,盡量為len。

3、減少修改字符串時帶來的內(nèi)存重分配次數(shù)

Redis主要通過以下兩種策略來處理內(nèi)存問題。

字符串長度增加操作時,進行空間預分配
字符串長度減少操作時,惰性空間釋放

當執(zhí)行字符串長度縮短的操作的時候,SDS并不直接重新分配多出來的字節(jié),而是修改len和free的值(len相應減小,free相應增大,buf的空間大小不變化),避免內(nèi)存重分配。

SDS也提供直接釋放未使用空間的API,在需要的時候,也能真正的釋放掉多余的空間。

4、二進制安全

C字符串除了末尾之外不能出現(xiàn)空字符,否則會被程序認為是字符串的結(jié)尾。這就使得C字符串只能存儲文本數(shù)據(jù),而不能保存圖像,音頻等二進制數(shù)據(jù)。

使用SDS就不需要依賴控制符,而是用len來指定存儲數(shù)據(jù)的大小,所有的SDS API都會以處理二進制的方式來處理SDS的buf的數(shù)據(jù)。程序不會對buf的數(shù)據(jù)做任何限制、過濾或假設,數(shù)據(jù)寫入的時候是什么,讀取的時候依然不變。

5、兼容部分C字符串函數(shù)

SDS的buf的定義(字符串末尾為’\0’)和C字符串完全相同,因此很多的C字符串的操作都是適用于SDS->buf的。比如當buf里面存的是文本字符串的時候,大多數(shù)通過調(diào)用C語言的函數(shù)就可以。

二、總結(jié)

C字符串    SDS
獲取字符串長度的復雜度為O(N)    獲取字符串長度的復雜度為O(1)
API是不安全的,可能會造成緩沖區(qū)溢出 API是安全的,不會造成緩沖區(qū)溢出
修改字符串長度N次必然需要執(zhí)行N次內(nèi)存重分配  修改字符串長度N次最多需要執(zhí)行N次內(nèi)存重分配
只能保存文本數(shù)據(jù)    可以保存文本或者二進制數(shù)據(jù)
可以使用所有庫中的函數(shù) 可以使用一部分庫的函數(shù)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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