1. 程式人生 > 其它 >redis資料結構---動態字串(SDS)

redis資料結構---動態字串(SDS)

Redis只會用C字串作為字面量,在大多數情況下Redis會使用SDS(Simple Dynamic String,簡單動態字串)作為字串表示。

Redis為什麼不用C字串(c字串與SDS的區別)

獲取字串長度複雜度

C語言使用N+1的字串陣列來表示長度為N的字串,並且陣列的最後一個元素總是空字串'/0',C字串並不記錄自身的長度資訊,每次獲取長度需要重新遍歷字串直到遇到'/0'為止,這個複雜度為O(N)。

SDS在len屬性中儲存了字串的長度,所以獲取字串長度的複雜度為O(1),設定和更新SDS長度的工作是由SDS的API在執行時自動完成的,不需要進行手動的修改。

杜絕緩衝區溢位

C字串如果在修改字串之前沒有分配足夠的記憶體空間會造成緩衝區溢位。

SDS在修改時會先檢查SDS的空間是否足夠,如果空間不足,會自動擴充套件空間至修改所需要的大小,再去執行修改操作。

減少修改字串時的記憶體分配次數

C字串的底層實現總是一個N+1個字元長度的陣列,因為C字串和底層陣列之間的長度存在這種關聯性,所以每次修改字串時會重新分配陣列的記憶體空間(如果增長字串而不進行重新分配記憶體會產生緩衝區溢位,減少的話會產生記憶體洩露)。

為了避免C字串的這種缺陷,SDS通過未使用空間解除了字串長度和底層陣列之間的關聯,在SDS中buff長度不一定是字元數量+1,數組裡面可以包含未使用的位元組,而這些位元組數量由SDS的free屬性記錄。

通過未使用空間,SDS實現了空間預分配和惰性空間釋放兩種優化策略。

空間預分配:

當對一個SDS進行修改並需要擴充套件SDS的空間時,程式不僅會分配修改所需要的空間,還會為SDS額外分配未使用的空間。(SDS小於1M會額外分配等於SDS的空間,大於等於1M則額外分配1M)

通過空間預分配策略,Redis可以減少連續執行字串增長操作所需的記憶體從新分配次數。(如果要增長的長度小於未使用的空間就不會重新分配記憶體)

惰性空間釋放:

惰性空間釋放用於優化SDS的字串縮短操作,當SDS需要縮短儲存的字串時,程式並不立即使用記憶體分配來回收縮短後多出來的位元組,而是使用free屬性將這些位元組數量記錄起來,並等待將來使用。

二進位制安全

C字串中的字元必須符合某種編碼格式,並且除了字串的末尾處,不允許有空字串,否則會被認為是字串結尾,這些限制使C字串只能儲存文字資料,不能儲存二進位制資料。

SDS會以處理二進位制的方式來處理SDS存放在buf陣列中的資料,程式不會對資料做任何限制,資料寫入時是什麼樣,讀取時就是什麼樣。(SDS的buf屬性不是儲存字元,而是儲存的一系列二進位制資料)