首頁 >資料庫 >Redis >Redis中SDS簡單動態字串問題怎麼解決

Redis中SDS簡單動態字串問題怎麼解決

王林
王林轉載
2023-05-26 12:50:201480瀏覽

一、SDS的結構 

c語言沒有string類型,本質是char[]數組;而且c語言數組創建時必須初始化大小,指定類型後就不能改變,並且字元數組的最後一個元素總是空字 '\0' 。

以下顯示了一個值為 "Redis" 的C 字串:

Redis中SDS簡單動態字串問題怎麼解決

#Redis沒有直接使用C語言的字串方式,而是建構了一種簡單動態字串(Simple dynamic string, SDS)的類型,Redis中的字串底層都是使用SDS結構進行存儲,例如包含字串的鍵值對底層都是使用SDS結構實現的。

SDS結構定義在sds.h中

struct sdshdr{


    int len;//SDS保存的字符串长度


    int free;//buf数组中未使用字节数量


    char buf[];//字符数组,保存字符串


}

Redis中SDS簡單動態字串問題怎麼解決

#最後一個位元組保存了空字元'\0',保留了C字串的規範,使得SDS結構的字串,可以重複使用一部分C函數庫的函數。

二、為什麼不使用C字串

主要是因為C字串有以下缺點:

取得字串長度時間複雜度為O(N):C字串取得長度需遍歷整個字串,遇到'\0'空字元為止。如果在進行字串追加操作時沒有分配足夠的內存,就會發生緩衝區溢位。記憶體重分配:每次增長或截短字串,程式都要對保存C字串的數組進行記憶體重新分配操作,而記憶體重分配涉及複雜的演算法,並可能需要執行系統調用,所以它通常比較耗時。空字元問題:C字串中間不能保存空格,否則程式遍歷是會誤認為字串的結尾。由於此限制,C字串只能用於儲存文字數據,而不適用於保存二進位資料如圖片、音訊視訊和壓縮檔案等。

三、怎麼解決C字串問題 

 Redis中SDS簡單動態字串問題怎麼解決

#1、SDS透過len屬性記錄了SDS長度,所以取得長度的時間複雜度為O( 1),即strlen指令的時間複雜度是O(1)。

2、SDS空間分配策略避免了緩衝區溢位:當SDS進行修改時,會先檢查SDS空間是否滿足修改,不滿足會自動擴展到所需大小,然後才執行修改。

3、較少修改字串時記憶體重新分配次數:SDS中的free記錄buf位元組數組中未使用的位元組。

redis透過free屬性實現空間預先分配、惰性空間釋放兩種最佳化策略。

空間預先分配:當對SDS進行成長操作時,程式不僅會分配修改所必須得空間,還會為SDS分配額外的未使用空間。記憶體重新分配次數在連續執行字串成長操作時得以減少,這是透過預先分配策略實現的。惰性空間釋放:當對SDS進行截短操作時,程式並不會立即回收縮短後多出來的位元組所佔用的內存,而是使用free屬性記錄多出來的位元組數,以供將來使用。未被使用的空間可能會在未來進行SDS成長時派上用場,此時成長作業不一定需要執行記憶體重新分配。

SDS結構中的buf位元組數組,是二進位安全的,不僅可以保存字符,也可以保存二進位資料。

SDS保留了C字串的慣例,將資料的末尾設定為空字元'\0',SDS中之所以保留這一規範是可以重用C字串函數庫的一部分函數,例如追加字串。

四、對字串的進一步最佳化

Redis string的三種編碼:

int 儲存8個位元組的長整數(long,2^63- 1 ) embstr, embstr格式的SDS (Simple Dynamic String) raw, raw格式的SDS,儲存大於44個位元組的長字串

int類型就是指的是數字,那麼raw、embstr都代表的是字串有什麼異同嗎,下面我們分析下。

Redis中SDS簡單動態字串問題怎麼解決

圖中展示了兩者的區別,可以看到embstr將redisObject和SDS保存在連續的64位元組空間內,這樣可以只需要一次記憶體分配,而對raw來說,SDS和redisObject分離,需要兩次記憶體分配,而且佔用更多的記憶體空間。

Redis中SDS簡單動態字串問題怎麼解決

可以看到embstr在3.2 中使用了叫做sdshdr8的結構,在這個結構下,元資料只需要3個位元組,而Redis需要8個位元組,所以總共64個字節,減去redisObject(16字節),再減去SDS的原信息,最後的實際內容就變成了44字節和39字節。

Redis中SDS簡單動態字串問題怎麼解決

當字串小於等於 44 位元組時,Redis 就使用了嵌入式字串的建立方法,以此減少記憶體分配和記憶體碎片。

下面這張圖展示了createEmbeddedStringObject 創建嵌入式字串的過程:

 Redis中SDS簡單動態字串問題怎麼解決

總之,只要記住,Redis 會透過設計實現一塊連續的記憶體空間,把redisObject 結構體和SDS 結構體緊密地放在一起。

這樣一來,對於不超過 44 個位元組的字串來說,就可以避免記憶體碎片和兩次記憶體分配的開銷了。

SDS是Redis中一種高效的字串實作方式,它具有自動擴容、二進位安全性、O(1)長度取得和修改等優點。在實際的應用中,SDS可以幫助我們實現高效的字串操作,同時也可以避免一些常見的字串操作問題,例如緩衝區溢位等。透過深入了解SDS的內部結構與實作原理,我們可以更能理解Redis的底層機制,進一步提升我們的Redis應用能力。

以上是Redis中SDS簡單動態字串問題怎麼解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除