《redis設計與實現》學習之SDS

最近在看《redis設計與實現(第二版)》這本書

《redis設計與實現》學習之SDS

此文一方面是對自我學習做一個鞏固和記錄,另一方面分享給有意提高自己知識面的小夥伴兒

由於鄙人看書一貫都是看著看著都快睡著了的狀態,所以看書對我來說其實是一種煎熬,但是我會慢慢適應逐漸改掉這個壞毛病。

剛看沒幾天,進度很慢。所以內容可能沒有之前那麼大篇幅和技術廣度。

言歸正傳。

Redis是一個開源的使用ANSI C語言編寫的可基於內存亦可持久化的日誌型、Key-Value數據庫。想必很多開發人員沒有沒聽過的吧?

Redis非常強大它支持存儲的value類型很多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。為了保證效率,數據都是緩存在內存中。

Redis的底層定義了一種數據結構動態字符串(simple dynamic string,SDS)來表示字符串值。

比如:執行命令

redis>set msg "hello word"

ok

那麼redis將在數據庫中創建一個鍵值對。鍵和值都是一個字符串對象。也就是說對於鍵msg,底層保存著一個字符串“msg”的sds,對於值hello world 底層同樣保存著字符串“hello world”的sds

再比如:

redis>rpush result "a" "b" "c"

(integer) 3

result鍵是一個保存了字符串"result"的sds,

其值是一個列表對象,這個對象包含三個字符串對象,這三個對象分別由三個sds實現:第一個sds保存著字符串"a",第二個sds保存"b",第三保存"c"

/** 保存字符串對象的結構*/struct sdshdr {  // buf 中已佔用空間的長度 int len; // buf 中剩餘可用空間的長度 int free; // 數據空間 char buf[];};

《redis設計與實現》學習之SDS

sds示例

① free屬性的值0,該SDS沒有空閒的未使用空間。

② len 為5,表示字符串的長度為5

③ buf為字符數組,最後一位為\0標識字符串的結束。

SDS遵循C字符串以空字符結束的慣例,保留空字符的1字節的空間,不計算在SDS的len屬性中,並且為空字符分配一個字節的空間,遵循這一慣例使得SDS仍然可以使用部分C語言字符串的一些函數。

sds相比C字符串有更多優勢:

時間複雜度低

對於獲取字符串長度而言,獲取c字符串操作的複雜度為O(N),而sds僅為O(1)。c字符串不記錄自身長度,為了獲取c字符串長度必須要遍歷整個字符串。而sds有其len屬性,記錄著sds本身的長度,不需要遍歷sds,直接取值就好了。

可以杜絕緩衝區溢出

這得益於sds的空間分配策略。sds api需要對sds進行修改時會先檢查sds空間是否滿足修改所需的要求,如果不滿足api會自動拓展sds空間再執行修改操作。


此外sds還有空間預分配和惰性空間釋放兩種優化策略,只要是減少內存重分配次數。

《redis設計與實現》學習之SDS


分享到:


相關文章: