1. 程式人生 > >Redis數據結構之簡單動態字符串

Redis數據結構之簡單動態字符串

文本 帶來 優化策略 增加 com 行修改 取字符串 常數 保存

  Redis沒有直接使用C語言傳統的字符串表示(以空字符結尾的字符數組), 而是自己構建了一種名為簡單動態字符串(simple dynamic string,SDS)的抽象類型, 並將SDS用作Redis的默認字符串表示。在Redis中,C字符串只會作為字符串字面量,用在一些無需對字符串值進行修改的地方,例如打印日誌。

一、SDS的結構定義

技術分享圖片

示例:

技術分享圖片

二、SDS與C字符串的區別
1. 常數復雜度獲取字符串長度
C字符串長度計算:遍歷整個字符串直至遇到代表字符串結尾的空字符,時間復雜度為O(N)。
SDS長度計算:只要訪問SDS的‘len‘屬性即可,時間復雜度為O(1)。
註:設置和更新SDS長度的工作是由SDS的API在執行時自動完成的,使用SDS無須進行任何手動修改長度的工作。


2. 杜絕緩沖區溢出
C字符串:增加長度時,需要開發者手動申請分配足夠的空間,否則會發生緩沖區溢出。
SDS:SDS的空間分配交由SDS API自動實現,無需手動申請分配,不會發生緩沖區溢出。
3. 減少修改字符串時帶來的內存重分配次數
C字符串:每次增長或縮短字符串,都需要進行一次內存重分配操作,否則會發生緩沖區溢出或內存泄漏。
SDS:通過使用"free"屬性記錄未使用空間,實現空間預分配和惰性空間釋放兩種優化策略,從而減少內存重分配次數。
(1)SDS空間預分配:
  SDS API對SDS的空間進行擴展的時候,不僅會為SDS分配必需的空間,還會分配額外的未使用空間。若修改後SDS長度小於1M,則預分配和"len"一樣大小的未使用空間;若修改後SDS長度大於等於1M,則預分配1M的未使用空間。以後再需要擴展SDS空間時,SDS API會優先使用SDS的"free"未使用空間。

(2)SDS惰性空間釋放:
  SDS API對SDS的空間進行縮短的時候,不會立即使用內存重分配來回收多余空間,而是使用"free"屬性將這些空間的字節數量記錄起來,等待以後使用。SDS也提供了相應的API,讓我們可以在有需要時,真正地釋放SDS中未使用的空間。
註:內存重分配涉及復雜的算法,並且可能需要執行系統調用,通常是一個比較耗時的操作,若頻繁執行可能會對性能造成影響。
4. 二進制安全
C字符串:字符必須符合某種編碼,而且除了字符串末尾,不能包含空字符,所以C字符串只能保存文本數據,而不能保存像圖片、音頻、視頻、壓縮文件這樣的二進制數據。
SDS:SDS API都是二進制安全的,可以保存任意格式的二進制數據。

5. 兼容部分C字符串函數
  SDS API總會將SDS保存的數據末尾設置為空字符,所以若SDS保存的是文本數據,則可以重用一部分<string.h>庫定義的函數,避免不必要的代碼重復。

三、SDS在Redis中的用途
1. 在Redis的數據庫中,包含字符串值的鍵值對在底層都是由SDS實現的。
2. 除此之外,SDS還被用作緩沖區,例如AOF模塊的AOF緩沖區、客戶端狀態中的輸入緩沖區。

Redis數據結構之簡單動態字符串