Redis的底層資料結構 SDS

2022-09-09 09:54:14 字數 1578 閱讀 6868

sds 定義:

struct sdshdr
用sds儲存字串 「redis」具體圖示如下:

我們看上面對於 sds 資料型別的定義:

1、len 儲存了sds儲存字串的長度

2、buf 陣列用來儲存字串的每個元素

3、free j記錄了 buf 陣列中未使用的位元組數量

上面的定義相對於 c 語言對於字串的定義,多出了 len 屬性以及 free 屬性。為什麼不使用c語言字串實現,而是使用 sds呢?這樣實現有什麼好處?

①、常數複雜度獲取字串長度

由於 len 屬性的存在,我們獲取 sds 字串的長度只需要讀取 len 屬性,時間複雜度為 o(1)。而對於 c 語言,獲取字串的長度通常是經過遍歷計數來實現的,時間複雜度為 o(n)。通過 strlen key 命令可以獲取 key 的字串長度。

②、杜絕緩衝區溢位

我們知道在 c 語言中使用 strcat  函式來進行兩個字串的拼接,一旦沒有分配足夠長度的記憶體空間,就會造成緩衝區溢位。而對於 sds 資料型別,在進行字元修改的時候,會首先根據記錄的 len 屬性檢查記憶體空間是否滿足需求,如果不滿足,會進行相應的空間擴充套件,然後在進行修改操作,所以不會出現緩衝區溢位。

③、減少修改字串的記憶體重新分配次數

c語言由於不記錄字串的長度,所以如果要修改字串,必須要重新分配記憶體(先釋放再申請),因為如果沒有重新分配,字串長度增大時會造成記憶體緩衝區溢位,字串長度減小時會造成記憶體洩露。

而對於sds,由於len屬性和free屬性的存在,對於修改字串sds實現了空間預分配和惰性空間釋放兩種策略:

1、空間預分配:對字串進行空間擴充套件的時候,擴充套件的記憶體比實際需要的多,這樣可以減少連續執行字串增長操作所需的記憶體重分配次數。

2、惰性空間釋放:對字串進行縮短操作時,程式不立即使用記憶體重新分配來**縮短後多餘的位元組,而是使用 free 屬性將這些位元組的數量記錄下來,等待後續使用。(當然sds也提供了相應的api,當我們有需要時,也可以手動釋放這些未使用的空間。)

④、二進位制安全

因為c字串以空字元作為字串結束的標識,而對於一些二進位制檔案(如等),內容可能包括空字串,因此c字串無法正確訪問;而所有 sds 的api 都是以處理二進位制的方式來處理 buf 裡面的元素,並且 sds 不是以空字串來判斷是否結束,而是以 len 屬性表示的長度來判斷字串是否結束。

⑤、相容部分 c 字串函式

雖然 sds 是二進位制安全的,但是一樣遵從每個字串都是以空字串結尾的慣例,這樣可以重用 c 語言庫中的一部分函式。

⑥、總結

一般來說,sds 除了儲存資料庫中的字串值以外,sds 還可以作為緩衝區(buffer):包括 aof 模組中的aof緩衝區以及客戶端狀態中的輸入緩衝區。

redis string底層資料結構SDS

通常,我們說redis 是用 c 語言寫的,但是對於redis的字串,卻不是 c 語言中的字串 即以空字元 0 結尾的字元陣列 它是自定義的資料結構sds dynamic string 並將 sds 作為 redis的預設字串表示。struct sdshdr用sds儲存字串 redis 具體圖示如下...

Redis底層資料結構?

福哥口訣法 簡鏈字跳整 壓快壓 sds synamic string 簡單動態字串。支援自動動態擴容的位元組陣列 list 鍊錶 雙端鍊錶。dict 字典。使用雙雜湊表實現的,支援平滑擴容的字典 zskiplist 跳躍表。附加了後向指標的跳躍表 intset 整數集合。用於儲存整數數值集合的自有結...

Redis底層資料結構

redis底層實現的8種資料結構 sds synamic string 支援自動動態擴容的位元組陣列 list 鍊錶 dict 使用雙雜湊表實現的,支援平滑擴容的字典 zskiplist 附加了後向指標的跳躍表 intset 用於儲存整數數值集合的自有結構 ziplist 一種實現上類似於tlv,但...