最近在看《redis設計與實現(第二版)》這本書
此文一方面是對自我學習做一個鞏固和記錄,另一方面分享給有意提高自己知識面的小夥伴兒
由於鄙人看書一貫都是看著看著都快睡著了的狀態,所以看書對我來說其實是一種煎熬,但是我會慢慢適應逐漸改掉這個壞毛病。
剛看沒幾天,進度很慢。所以內容可能沒有之前那麼大篇幅和技術廣度。
言歸正傳。
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[];};
① 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還有空間預分配和惰性空間釋放兩種優化策略,只要是減少內存重分配次數。
閱讀更多 碼農的搬磚生涯 的文章