一、基本原理redis
Redis 的字符串是動態字符串,是能夠修改的字符串,內部結構實現上相似於 Java 的 ArrayList,採用預分配冗餘空間的方式來減小內存的頻繁分配,如圖中所示,內部爲當前字符串實際分配的空間 capacity 通常要高於實際字符串長度 len。當字符串長度小於 1M 時, 擴容都是加倍現有的空間,若是超過 1M,擴容時一次只會多擴 1M 的空間。須要注意的是 字符串最大長度爲 512M。api
二、數據結構安全
struct sdshdr { // buf 中已佔用空間的長度 int len; // buf 中剩餘可用空間的長度 int alloc; //前3位爲數據類型,後5位暫時沒有用到 unsigned char flags; // 數據空間 char buf[]; };
三、SDS 與C字符串的對比 和優勢數據結構
a O(1) 獲取字符串長度函數
由於sds已經存了數據的長度,因此獲取字符串長度複雜度爲O(1),而C字符串獲取長度爲O(n)。優化
b 杜絕緩衝區溢出致使的內存問題編碼
假設內存區域有s1:「hi」,s2: 「redis」 兩個字符串,位置緊鄰,以下圖: 緊鄰字符串被覆蓋 此時須要給s1 追加一個「boy」, 若是是C字符串,忘記了在追加以前先給s1 分配空間,此時追加將致使 s2的值被意外的修改。 而使用 sds則不會有這個問題。 由於其封裝好的函數,會在追加數據以前先檢查 空間是否夠用,若是不夠用就擴容。code
c 經過空間預分配和空間惰性釋放圖片
減小內存分配問題 當給sds的值追加一個字符串,而當前的剩餘空間不夠時,就會觸發sds的擴容機制。擴容採用了空間預分配的優化策略,即分配空間的時候:若是sds 值大小< 1M ,則增長一倍; 反之若是>1M , 則當前空間加1M做爲新的空間。 當sds的字符竄縮短了,sds的buf內會多出來一些空間,這個空間並不會立刻被回收,而是暫時留着以防再用的時候進行多餘的內存分配。這個是惰性空間釋放的策略內存
d 二進制安全
c字符串必須符合某種編碼(例如ASCII),且不能包含空字符。 這些限制使得 c字符竄不能保存圖片,音頻等二進制文件。 而sds的api 都是二進制安全的,其全部api 都會以處理二進制的方式來處理buf內的數據,因此不會有任何的限制。