Redis設計與實現之SDS和鍊錶

2021-10-25 09:15:26 字數 2113 閱讀 7740

比如我們可以在redis客戶端敲

redis> set msg "helloredis"
那麼就會在redis資料庫中建立乙個新的鍵值對,keg是msg,value是helloredis,兩個都是sds。

又比如在redis客戶端敲

redis>rpush number 1 2 3
這也就是乙個list物件(列表物件),numbe為鍵,1,2,3為值。經過這幾個小的例子你會發現redis的用法很簡單,sds還可以被用來作緩衝區(buffer):aof模組的aof緩衝區和客戶端狀態中的輸入緩衝區。

說了這麼多的sds,那麼到底什麼是sds,sds又是怎麼實現的呢,那它又和我們傳統的字串有什麼區別呢?

我們可以用c的結構體來表示sds的定義資訊

struct sds
那這些都是代表什麼意思呢?

len:用來記錄字串的長度,也就是buf已使用的位元組數量

free:用來記錄buf中剩餘的數量

buf:是乙個char陣列,用來儲存字串的每個字元,字串最後必須是乙個空字元』\0』,不占用空間但是占用位置。這些新增字串字尾都是由redis的內部函式來實現。

不止這一點redis的設計和c很像,redis還有很多和c相同的地方,因為這樣就可以直接重用一些c寫好的函式。

現在是不是對sds有一些了解了,從結構可以看出它比c中的字串多了len和free,這寫引數可以決定怎樣的效能呢?

redis獲取字串長度時間複雜度低,保證了效率

sds不會造成緩衝去溢位

這個原因的實質還是因為沒有len,我們假設在計算機記憶體中按順序排列著s1,s2字串,s2緊跟著s1字串。如果是普通字串進行拼接操作

sds會很大程度減少記憶體重分配次數

為什麼這麼說呢?相信大家以前也做過字串修改的函式,我們當時函式底層是怎樣的呢?在我們每次修改字串時系統都會執行記憶體重分配演算法,如果不經常修改的話這都不是問題(前提是不粗心,不然增的時候可能會造成記憶體溢位,刪的時候可能會造成記憶體洩漏),但是資料庫就不一樣,因為資料庫的修改操作很頻繁,因此redis採用的快取策略。

二進位制安全

這個也是c中的字串中比較難受的事情了,比如我們輸入一串數字再加上空格再加上一串數字,c就只會把它的前一段寫進去,因為c判斷結束的標識是空字元。但是redis就不會出現這種問題,輸入進去什麼樣子,輸出出來就是什麼樣子,為什麼呢?歸根結底還是因為有len,因為它可以記住個數而不是一味的根據空字元來判斷是不是結束了,因此它上邊就可以存任何型別的東西。比如傳一串二進位制字串,c可能得需要很複雜的處理,但是redis根據sds的定義就可以很輕鬆的解決這個問題。那redis可以不給末尾加\0也可以實現為什麼要加,還是因為它可以重用一些c的庫函式。

總結:sds相對於普通字串的優點(歸根結都還是結構體的設計問題)

因為c裡沒有鍊錶庫,因此redis就自己實現了鍊錶,那煉表在redis中扮演乙個什麼的角色呢?它在redis中的應用非常廣泛,比如鍊錶鍵,發布與訂閱,慢查詢,監視器等功能,redis伺服器本身還使用鍊錶來儲存客戶端的狀態資訊。

鍊錶的操作就很簡單了,因為它就和糖葫蘆一樣乙個乙個穿成一串。沒有寫過或者了解鍊錶的可以去一些資料結構或者演算法導論等一些書上去參考更詳細的,我這就講個中心意思。

設計資料結構模型,給node模型加上前驅和後記和節點的值。

typedef struct listnodelistnode;
然後就通過指標操作頭插或尾插進行連線成乙個雙向鍊錶。

但是redis是以高效能著稱的,按照上述設計那不就是乙個普通的單鏈表麼,因此個資料結構仍有改進的空間。redis後來就自己設計了如下結構的節點結構。

typedef struct listlist;
這種相對於上一種的優勢所在是帶有長度計數器,和節點的特定函式。

可以總的來說一下redis的鍊錶實現的特性:

1.雙向鍊錶獲取前驅和後繼的時間複雜度都是o(1)

2.是乙個沒有頭節點的鍊錶,最小是空

3.帶有表頭和表尾,獲取頭和尾時間複雜度為o(1)

4.多種功能:幾個特殊設定的函式,可用於儲存各種不同型別的值

雖然感覺上述這些並不是很難懂,但是它都設計的很巧妙,對查詢和修改都優化了不少。

redis設計與實現讀書筆記二 SDS

redis字串並沒有使用以空字元為結尾的字元陣列來構建,而是實現了一套自身的字串模式,也叫簡單動態字串 sds,dynamic string sds在sds.h sdshdr中如下表示 struct sdshdrsds遵循c字串的已空字元結尾的慣例,這樣sds便可以復用c字串函式庫的一些函式.無須為...

《REDIS設計與實現》讀書筆記之一 SDS型別

sds型別是 danamic string的縮寫,即為簡單動態字串,redis使用這個型別來替換c語言中的基礎型別char字串,好處顯而易見,c語言程式都很容易理解 減低獲取字串長度的複雜度,防止字串溢位,減少記憶體的分配釋放次數,二進位制安全,相容c標準庫等。這些都是很容易理解的,c語言程式設計師...

Redis 設計與實現 3 字串 SDS

在 redis 中,字串都用自定義的結構簡單動態字串 dynamic strings,sds redis 中使用到的字串都是用 sds,例如 key string 型別的值 sorted set 的 member hash 的 field 等等等等。資料結構 舊版本的結構 在 3.2 版本之前,sd...