redis資料結構實現(一)

平行宙宇發表於2018-11-20

redis資料結構實現(一)

1. SDS簡單動態字串詳解

sds是redis自己實現的一種資料結構,用來作為redis底層預設字串,與c語言的字串區別開來。
在redis中c字串一般用於不需要改變的字串值,叫做字串字面量,如:列印日誌。
redis中每對鍵值的鍵都是一個sds物件。

傳統c字串與sds比較:

  • sds資料結構中也是用字元陣列儲存字串,但是帶有兩個額外引數:len(記錄字串長度)和free(未使用空間)
  • 想要獲得傳統c字串的長度不得不遍歷整個字串,然而sds則可直接讀取len值。降低了時間複雜度
  • 兩者的字元陣列都是以空字元`/0`結尾,在sds中此空字元不計入len中但是也同樣分配一個位元組空間,空字元的相關操作都是由sds的API自動完成的,所以對於開發者來說此空字元是透明的。sds保持和c字串一致以空字元作為結尾是為了能夠複用c語言的字串函式庫裡的函式。
  • 傳統c字串如果在對字串操作沒有注意空間剩餘有可能會出現內場溢位的現象,而sds的API中執行拼接操作的函式sdscat,拼接時會先判斷空間是否足夠,如果不夠則會先執行擴容操作,從而杜絕內場溢位.
  • 避免頻繁記憶體重分配:傳統c字串的長度為n+1(空字元),每一次append時需要重新分配記憶體,否則記憶體溢位;如果trim字串,後面不需要的空間也要釋放,否則記憶體洩露。記憶體重分配設計複雜演算法且可能需要系統排程,不符合redis的速度要求。而sds通過free-未使用空間來解除了底層陣列長度與字串長度間的關聯,sds擁有空間預分配與惰性空間釋放兩鍾優化策略。

    1. 空間預分配

      在對sds空間擴充時,先判斷空間是否足夠,如果足夠,則直接使用未使用空間。如果空間不夠則使用空間預分配策略
      如果計算得出的sds修改後的長度小於1MB,那麼預分配的未使用空間將於已使用的空間一樣長。如果sds修改後的長度大於1MB,
      那麼將分配1MB的未使用空間。
      通過這種策略將連續增長N次的sds字串所需的記憶體重分配次數從必定是N次改為最多N次。
    2. 惰性空間釋放

      在對sds字串進行縮短操作時,並不立即回收縮短的長度,而是利用free將縮短的字串記錄起來,以備以後擴充時使用。
      同樣sdsAPI中也提供了真正回收空間的API,所以惰性空間釋放並不會浪費空間。
    • 二進位制安全:c字串必須得符合某種編碼,且字串除了尾部中間不能存放空字元,否則被讀取到空字元時忽略後面的字元段。所有c字串只能存放文字資訊不能存放二進位制資料。而sds的API都是二進位制安全(binary-safe)的,buf中存放的就是一系列二進位制資料。


相關文章