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...