資料結構 動態字串SDS

2021-10-10 16:52:19 字數 2393 閱讀 7273

c語言使用的這種簡單的字串表示方式, 並不能滿足redis對字串在安全性、 效率以及功能方面的要求,sds比c字串更適用於redis

和c 字串不同, 因為 sds 在len屬性中記錄了 sds 本身的長度, 所以獲取乙個 sds 長 度的複雜度僅為o(1)。而c是o(n)

除了獲取字串長度的複雜度高之外, c字串不記錄自身長度帶來的另乙個問題是容易造成緩衝區溢位( buffer overflow )。

與c字串不同, sds的空間分配策略完全杜絕了發生緩衝區溢位的可能性: 當 sds api需要對sds進行修改時, api會先檢查 sos 的空間是否滿足修改所需的要求, 如果不滿足的話, api會自動將sos 的空間擴充套件至執行修改所需的大小, 然後才執行實際的修改操作, 所以使用sos 既不需要手動修改sos 的空間大小, 也 不會出現前面所說的緩衝區溢 出問題。

因為c字串的長度和底層陣列的長度 之間存在著這種關聯性 所以每次增長或者縮短乙個c字串 , 程式都總要對儲存這個c字串的陣列進行一次記憶體重分配操作。為了避免c字串的這種缺陷,sds 通過未使用空間解除了字串長度和底層陣列長度之間的關聯:在 sds 中,buf 陣列的長度不一定就是字元數量加一,**陣列裡面可以包含未使用的位元組,**而這些位元組的數量就由 sds 的 free 屬性記錄。通過未使用空間,sds 實現了空間預分配和惰性空間釋放兩種優化策略。

1.空間預分配

空間預分配用於優化 sds 的字串增長操作: 當sds的 api 對乙個 sds 進行修改,並且需要對 sds 進行空間擴充套件的時候,程式不僅會為 sds 分配修改所必須要的空間,還會為 sds 分配額外的未使用空間。

其中,額外分配的未使用空間數量由以下公式決定:

如果對 sds 進行修改之後,sds 的長度(也即是 len 屬性的值)小於 1mb,那麼程式分配和 len 屬性同樣大小的未使用空間,這時 sds len 屬性的值將和 free 屬性的值相同。

如果對sds進行修改之後, sds 的長度將大於等於1m那麼程式會分配 1mb的未使用空間。

通過空間預分配策略,redis 可以減少連續執行字 符串增長操作所需的記憶體重分配次數。

在擴充套件 sds空間之前, sdsapi會先檢查未使用空間是否足夠, 如果足夠的話, api 就會直接使用未使用空間, 而無須執行記憶體重分配。

通過這種預分配策略, sds將連續增長n次字串所需的記憶體重分配次數從必定n次降低為最多n次。

2.惰性空間釋放

惰性空間釋放用於優化sds 的字串縮短操作: 當 sds的api需要縮短 sds儲存的字串時, 程式並不立即使用記憶體重分配來**縮短後多出來的位元組, 而是使用free屬性 將這些位元組的數量記錄起來, 並等待將來使用。

通過惰性空間釋放策略, sds避免了縮短字串時所需的記憶體重分配操作, 並為將來可能有的增長操作提供了優化。與此同時, sds也提供了相應的api, 讓我們可以在有需要時, 真正地釋放 sds的未使用空間, 所以不用擔心惰性空間釋放策略會造成記憶體浪費。

雖然sds的api都是二進位制安全的, 但它們一樣遵循c字串以空字元結尾的慣例: 這些api總會將sds儲存的資料的末尾設定為空字元, 並且總會在為buf陣列分配空間時多分配乙個位元組來容納這個空字元, 這是為了讓那些儲存文字資料的sds可以重用一部分

redis中的動態sds和c語言自帶字串的區別:

1、常數複雜度獲取字串長度,對於sds,直接讀取len屬性即可知道字串長度,而對於c語言自帶,則常常通過遍歷得到字串長度;2、避免緩衝區溢位:對字串修改時,會檢查len屬性是否滿足要求,如果不滿足則需要對sds進行相應的擴容,不會發生相應的記憶體溢位,而c語言會;

3、減少記憶體重分配次數:sds中存在len和free屬性,通過free解除了字串長度和底層陣列長度之間的關聯:在 sds 中,buf 陣列的長度不一定就是字元數量加一,陣列裡面可以包含未使用的位元組,而這些位元組的數量就由 sds 的 free 屬性記錄。通過未使用空間, sds 實現了空間預分配和惰性空間釋放兩種優化策略。

空間預分配指的是空間擴充套件時分配多於需要的空間,

空間惰性釋放指的是通過free記錄空閒空間以便後面使用,而c語言每次修改都需要重新分配空間,否則會造成空間溢位或洩露;

4、二進位制安全:c語言對二進位制資訊()中存在空格時無法正確訪問,以空格作為字串結束標誌,而sds則完全依靠二進位制處理資訊,依據len屬性判斷字串結束;

Redis資料結構 SDS(簡單動態字串)

redis中所有字串都是用sds 簡單動態字串 實現的,該結構體內部定義如下 struct sdshdr 關於sds的特點,可以總結為以下幾點 1.sds遵循c字串以空字元結尾的風格,相容部分c字串函式,buf在末尾缺省會帶上乙個 0 字元,但是不會計算到len欄位裡面,因此buf的實際大小為len...

Redis資料結構 簡單動態字串SDS

最新 redis記憶體 三個重要的緩衝區 最新 redis記憶體 記憶體消耗 記憶體都去哪了?最新 redis持久化 如何選擇合適的持久化方式 最新 redis持久化 aof日誌 相信用過redis的人都知道,redis提供了乙個邏輯上的物件系統構建了乙個鍵值對資料庫以供客戶端使用者使用。這個物件系...

Redis資料結構 簡單動態字串 SDS

redis沒有使用c中預設的字串 字元陣列 而是自己構建了乙個簡單動態字串 sds 的抽象型別,並且作為預設的字串。sds.h sdshdr結構體表示乙個sds值 struct sdshdr 相比普通的c字串,sds的優點在於 在使用sds api進行字串修改需要擴容時,不僅會分配修改所必須的空間,...