redis資料型別設計和實現 之一 字串型別

2021-07-11 21:08:18 字數 2248 閱讀 5613

字串型別

最近一直在研究redis的資料型別的底層實現,大神推薦的書《redis設計與實現》。從今天起一點一點分解本書所講解的知識並同步部落格來記錄學習過程以及當做將來的複習資料,同時也希望和有相同興趣的同學一起學習共同進步。由於個人水平有限,還望看過朋友不吝賜教指正文中理解不足或是錯誤的地方,本人不勝感激。

今天先從redis最簡單的資料型別說起--字串型別,好了廢話不多說。

一、sds(簡單動態字串)

下圖新增了一組鍵值對其中鍵名為"test" 值為"redis"。

儲存成功後,我們看到「test」和「redis」都是乙個字串,那麼問題就來了,redis是怎樣儲存鍵值對的呢?

實際上,在redis的儲存中,上述的鍵「test」和值「redis」都是使用的redis的字串型別進行儲存。但redis的字串型別底層實現並沒有直接使用c語言中的字串型別,而使用的是自己構建的一套名為簡單動態字串抽象型別,簡稱為:sds。

也就是說:鍵"test"是使用乙個sds型別進行儲存;值「redis」也是使用的乙個sds進行儲存。

二、sds的組成

sds由3個字段組組成分別是:len、free、buf,偽**表示,

len:int型別,用來記錄欄位buf陣列已經使用的位元組的數量,也就是sds的字串的實際長度。

free:int型別,用來記錄欄位buf陣列未使用的的位元組的數量。

buf:位元組陣列,用來儲存字串。

三、sds與c字串型別區別和優點

a.儲存格式不同。傳統中,c字串型別使用長度為n+1的字元陣列來儲存長度為n的字串,而且字元陣列的最後乙個元素總是乙個空字元'\0'(這種字串的儲存方式在很多方面限制了c字串型別在redis中廣泛的使用)。雖然在sds中字串儲存在屬性欄位buf的位元組陣列中字串結尾處也是用乙個空字串'\0'來表示,但是c中'\0'表示字串的結束結尾沒有任何可用空間,而sds中'\0'只是字串偽結尾不表示字串的結束,空字元'\0'後面還可能有可用的空間。如果有可用空間,屬性欄位free記錄可用空間的長度。優點:sds能夠相容一些c字串函式,不用sds再重新寫新的api函式。

b.獲取字串長度方式。c字串型別獲取字串長度則要從字串的開始位置計算直到count到結尾元素'\0',複雜度為o(n);sds獲取字串的長度只需要讀取len屬性字段值即可,複雜度為o(1)。優點:做出對比就可以知道兩種字串獲取字串長度的效率是不一樣的,sds明顯優於c字串。

d.二進位制安全。c字串型別的結尾'\0'元素,限制了c儲存二進位制資料的安全性。如果如果某種二進位制資料中有'\0'空字元,則c會認為這是字串的結束,從而導致出現資料的破壞。sds則沒有這種限制,因為sds讀取資料的結尾是靠len欄位大小確定的。二進位制資料放進來是什麼樣,出去的時候還是什麼樣的,sds就當不認識空字元'\0',當然就不會破壞資料。優點更明顯了:sds儲存二進位制資料更安全。

四、sds的空間預分配策略

空間預分配這種方式是為了優化sds字串增長的操作。sds的api在增長字串判斷需要增加空間時,程式不僅會分配修改所需要的空間,還會分配一些額外的未使用的空間,額外的未使用的空間的大小是根據以下公式確定的:

1.當完成修改後sds空間小於1m是,即len的數量小於1m,程式會分配額和len數量同樣大的未使用的空間。比如:乙個sds原來有10個位元組的字串,要在增加5個位元組長度的字串,sds需要進行擴充套件,擴充套件後的sds空間的大小為:15+15+1=31個位元組。已使用空間大小15個位元組小於1m,再加上分配的未使用的15個位元組的空間,再加上1個位元組的結尾空字元'\0'占用空間。

2.當修改完成後sds空間大於等於1m,即len的數量大於等於1m,程式只分配1m的未使用空間。此舉在於節省記憶體空間,因為如果存在大量的超過1m的sds,都為其分配相等的未使用空間,記憶體浪費是相當嚴重的。

總結:redis使用了自己構建的sds型別來存字串,sds相較於c字串優勢在於:高效率,更安全,功能更強大。

Redis之資料型別

與mysql資料庫支援的多種資料型別相比,redis資料庫支援的資料型別要少上許多。redis資料庫支援五種資料型別 string 字串 hash 雜湊 list 列表 set 集合 及zset sorted set 有序集合 string 是 redis 最基本的型別,你可以理解成與 memcac...

Redis 資料型別之雜湊型別

營口小書生 2017 05 11 15 26 redis 有很多種型別,現在我們不用想太多,看此篇文章,你只需要記得你 雜湊型別 就好 雜湊型別顧名思義就是字段分開儲存的,可以自由更改值,不需要先讀取整篇內容在更改其中乙個 然後在儲存更新原有的,這樣是不是很簡單啊,還能保證資料的一致性,不用擔心改錯...

Redis資料型別之ZSet型別

有序集合 sorted set 1 redis 有序集合和集合一樣,也是string型別元素的集合,且不允許有重複的成員。2 不同的是每個元素都會關聯乙個double型別的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。3 有序集合的成員是唯一的,但分數 score 卻可以重複。4 ...