Redis中Srting型別的底層實現 SDS

2021-10-24 06:28:52 字數 1782 閱讀 6712

sds是c中的乙個資料結構,如下:

struct sdshdr
redis中用這種資料結構來儲存string型別

c/c++ 中 char 陣列也可以儲存字串,而且c就是這麼幹的, c 語言使用長度為 n+1 的字元陣列來表示長度為 n 的字串, 並且字元陣列的最後乙個元素總是空字元 '\0' 。

我們分析一下以下幾種情況char陣列和sds的區別:

2.1. 長度的獲取。

c中字串長度獲取需要遍歷char陣列,時間複雜度是o(n)

sds直接記錄了字串的長度,所以長度獲取的時間複雜度是o(1)

2.2. 緩衝區溢位(buffer overflow)

除了獲取字串長度的複雜度高之外, c 字串不記錄自身長度帶來的另乙個問題是容易造成緩衝區溢位(buffer overflow)。 /strcat 函式可以將 src 字串中的內容拼接到 dest 字串的末尾,當dest拼接的src的長度超過自身分配的位址大小時,就會修改到別的位址,造成緩衝區溢位。

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

2.3. 空間預分配

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

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

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

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

舉個例子: 如果進行修改之後, sds 的 len 將變成 13 位元組, 那麼程式也會分配 13位元組的未使用空間, sds 的 buf 陣列的實際長度將變成: 13 + 13 + 1 = 27 位元組(額外的一位元組用於儲存空字元)。

如果sds 的 len 將變成 30 mb , 那麼程式會分配 1 mb 的未使用空間, sds 的 buf 陣列的實際長度將為 30 mb + 1 mb + 1 byte 。 通過空間預分配策略, redis 可以減少連續執行字串增長操作所需的記憶體重分配次數。

2.4. 惰性空間釋放

簡單的說,sds在使用sds api減少字串長度的時候,並不會立馬釋放縮短後多出來的位元組,萬一下次又用到了呢,是吧。

2.5. 二進位制安全

雖然資料庫一般用於儲存文字資料, 但使用資料庫來儲存二進位制資料的場景也不少見, 因此, 為了確保 redis 可以適用於各種不同的使用場景, sds 的 api 都是二進位制安全的(binary-safe): 所有 sds api 都會以處理二進位制的方式來處理 sds 存放在 buf 陣列裡的資料, 程式不會對其中的資料做任何限制、過濾、或者假設 —— 資料在寫入時是什麼樣的, 它被讀取時就是什麼樣。

這也是我們將 sds 的 buf 屬性稱為位元組陣列的原因 —— redis 不是用這個陣列來儲存字元, 而是用它來儲存一系列二進位制資料。

不要侷限於現有的資料結構,多思考一下,結合實際應用場景選擇符合自己的最佳結構。

空間換時間真是個不錯的選擇。

redis中的set型別

redis中set型別是一種無序集合,在redis內部通過hashtable實現,set資料型別的優點是快速找到某個元素是否存在,用於記錄一些不能重複的值,例如 註冊的時候使用者名稱不能重複。set有如下命令 1 sadd key member 新增乙個字串型別的元素到key對應的set集合中。2 ...

Redis中的set儲存型別

在redis中,我們可以將set型別看作為沒有排序的字元集合,和list型別一樣,我們也可以在該型別的資料值上執行新增 刪除或判斷某一元素是否存在等操作。和list型別不同的是,set集合中不允許出現重複的元素,這一點和c 標準庫中的set容器是完全相同的。換句話說,如果多次新增相同元素,set中將...

Redis中的資料型別

redis支援5中資料型別 string 字串 hash 雜湊 list 列表 set 集合 zset 有序集合 string string型別是redis最基本的型別,乙個key對應於乙個value,並且是二進位制安全的,即可以包含任何資料,包括或者序列化的物件 突然想起python的pil中的i...