Redis資料結構 簡單動態字串SDS

2022-01-10 08:23:53 字數 3245 閱讀 3205

最新:redis記憶體——三個重要的緩衝區

最新:redis記憶體——記憶體消耗(記憶體都去哪了?)

最新:redis持久化——如何選擇合適的持久化方式

最新:redis持久化——aof日誌

相信用過redis的人都知道,redis提供了乙個邏輯上的物件系統構建了乙個鍵值對資料庫以供客戶端使用者使用。這個物件系統包括字串物件,雜湊物件,列表物件,集合物件,有序集合物件等。但是redis面向記憶體並沒有直接使用這些物件。而是使用了簡單動態字串,鍊錶,字典(雜湊表),跳躍表,整數集合,壓縮列表這些資料結構來操作記憶體。

redis預設並未直接使用c字串(c字串僅僅作為字串字面量,用在一些無需對字串進行修改的地方,如列印日誌)。而是以struct的形式構造了乙個sds的抽象型別。當redis需要乙個可以被修改的字串時,就會使用sds來表示。在redis資料庫裡,包含字串值的鍵值對都是由sds實現的(redis中所有的鍵都是由字串物件實現的即底層是由sds實現,redis中所有的值物件中包含的字串物件底層也是由sds實現)。

上圖表示了sds與c字串的區別,關於為什麼redis要使用sds而不是c字串,我們可以從以下幾個方面來分析。

2.1 緩衝區溢位

c字串,如果程式設計師在字串修改的時候如果忘記給字串重新分配足夠的空間,那麼就會發生記憶體溢位,如上圖所示,忘記給s1分配足夠的記憶體空間, s1的資料就會溢位到s2的空間, 導致s2的內容被修改.。而redis提供的sds其內建的空間分配策略則可以完全杜絕這種事情的發生。當api需要對sds進行修改時, api會首先會檢查sds的空間是否滿足條件, 如果不滿足, api會自動對它動態擴充套件, 然後再進行修改。

2.2 記憶體重分配

2.2.1 c字串記憶體重分配

在c字串中,如果對字串進行修改,那麼我們就不得不面臨記憶體重分配。因為c字串是由乙個n+1長度的陣列組成,如果字串的長度變長,我們就必須對陣列進行擴容,否則會產生記憶體溢位。而如果字串長度變短,我們就必須釋放掉不再使用的空間,否則會發生記憶體洩漏。

2.2.2 sds空間分配策略

對於redis這種具有高效能要求的記憶體資料庫,如果每次修改字串都要進行記憶體重分配,無疑是巨大的效能損失。而redis的sds提供了兩種空間分配策略來解決這個問題。

空間預分配

我們知道在陣列進行擴容的時候,往往會申請乙個更大的陣列,然後把陣列複製過去。為了提公升效能,我們在分配空間的時候並不是分配乙個剛剛好的空間,而是分配乙個更大的空間。redis同樣基於這種策略提供了空間預分配。當執行字串增長操作並且需要擴充套件記憶體時,程式不僅僅會給sds分配必需的空間還會分配額外的未使用空間,其長度存到free屬性中。其分配策略如下:

惰性空間釋放

惰性空間釋放用於字串縮短的操作。當字串縮短是,程式並不是立即使用記憶體重分配來**縮短出來的位元組,而是使用free屬性記錄起來,並等待將來使用。

redis通過空間預分配和惰性空間釋放策略在字串操作中一定程度上減少了記憶體重分配的次數。但這種策略同樣會造成一定的記憶體浪費,因此redis sds api提供相應的api讓我們在有需要的時候真正的釋放sds的未使用空間。

2.3 二進位制安全

2.4 時間複雜度

我們來看幾個redis常見操作的時間複雜度。

獲取sds長度: 由於sds中提供了len屬性,因此我們可以直接獲取時間複雜度為o(1),c字串為o(n)。

獲取sds未使用空間長度: 時間複雜度為0(1),原因同1。

清除sds儲存的內容:由於惰性空間分配策略,複雜度為o(1)。

建立乙個長度為n的字串:時間複雜度為o(n)。

拼接乙個長度為n的c字串:時間複雜度為o(n)。

拼接乙個長度為n的sds字串:時間複雜度為o(n)。

redis在獲取字串長度上的時間複雜度為常數級o(1)。

2.5 為什麼要使用sds

通過以上分析,我們可以得到,sds這種資料結構相對於c字串有以下優點:

redis定位於乙個高效能的記憶體資料庫,其面向的就是大資料量,大併發,頻繁讀寫,高響應速度的業務。因此在保證安全穩定的情況下,效能的提公升非常重要。而sds這種資料結構遮蔽了c字串的一些缺點,可以提供安全高效能的字串操作。

redis在網際網路專案中的應用越來越廣泛,會用只是學習redis中最簡單的一步,要想真正的成為redis高手,了解其底層的實現必不可少。本篇文章簡單介紹了redis中sds資料結構及其特性,分析了redis sds的空間分配策略和其與c字串相比的優勢,後續的文章將繼續分享redis底層實現的其它資料結構。未完待續......

最新:redis記憶體——三個重要的緩衝區

最新:redis記憶體——記憶體消耗(記憶體都去哪了?)

最新:redis持久化——如何選擇合適的持久化方式

最新:redis持久化——aof日誌

redis持久化——記憶體快照(rdb)

一文回顧redis五大物件(資料型別)

redis物件——有序集合(zset)

redis物件——集合(set)

redis物件——列表(list)

redis物件——雜湊(hash)

redis資料結構——quicklist

redis物件——字串

redis物件——redis物件系統簡介

redis資料結構——壓縮列表

redis資料結構——整數集合

redis資料結構——跳躍表

redis資料結構——字典

redis資料結構——鍊錶

redis資料結構——簡單動態字串sds

Redis 資料結構 簡單動態字串

redis 是基於 c 語言的記憶體資料庫,但是 redis 中並沒有使用 c 語言的字串 實質是 以空格結尾的字元陣列 作為預設的字串,而是自己構建了一種名為簡單動態字串 dynamic string 的抽象資料結構,將其用作預設的字串表示。通常而言,sds 在 redis 中被用於 1.預設的字...

Redis資料結構 SDS(簡單動態字串)

redis中所有字串都是用sds 簡單動態字串 實現的,該結構體內部定義如下 struct sdshdr 關於sds的特點,可以總結為以下幾點 1.sds遵循c字串以空字元結尾的風格,相容部分c字串函式,buf在末尾缺省會帶上乙個 0 字元,但是不會計算到len欄位裡面,因此buf的實際大小為len...

Redis資料結構 簡單的動態字串

c語言中的字串是基於陣列來實現的,每個字串會多出乙個空字元 redis中的簡單動態字串是sds dynamic string 型別 sds遵循c語言中以空字元為結尾的慣例是為了利用c語言函式庫中的某些字串函式,而且新增空字元的這乙個操作是有sds函式自動完成的。redis採用sds的原因是為了滿足字...