Redis沒有直接使用C語言傳統的字符串表示(以空字符結尾的字符數組,以下簡稱C字符串),而是自己構建了一種名為簡單動態字符串(simple dynamic string,SDS)的抽象類型,並將SDS用作Redis的默認字符串表示。
當Redis需要的不僅僅是一個字符串面量,而是一個可以被修改的字符串值時,Redis就會使用SDS來表示字符串值,比如在Redis的數據庫里,包含字符串值得鍵值對在底層都是由SDS來實現得。
客戶端執行命令
set msg "hello world"
那么Redis將在數據庫中創建一個新得鍵值對,其中
鍵值對得鍵是一個字符串對象,對象得底層實現是一個保存着字符串“msg”的SDS
鍵值對的值也是一個字符串對象,對象的底層實現是一個保存着字符串“hello world”的SDS
又比如,客戶端執行命令
rpush fruits “apple” “banana” “cherry”
那么Redis將在數據庫中創建一個新的鍵值對,其中
鍵值對的鍵是一個字符串對象,對象底層實現是一個保存了字符串“fruits”的SDS
鍵值對的值是一個列表對象,列表對象包含了三個字符串對象,這三個字符串對象分別由三個SDS實現:第一個SDS保存着字符串“apple”,第二個SDS保存着字符串“banana”,第三個SDS保存着字符串“cherry”
除了用來保存數據庫中的字符串值之外,SDS還被用作緩沖區:AOF模塊zhong的AOF緩沖區,以及客戶端狀態中的輸入緩沖區,都是由SDS實現的。
一、SDS的定義
結構如下圖
free 屬性的值為0,表示這個SDS沒有分配任何未使用空間
len 屬性的值為5,表示這個SDS保存了一個五字節長的字符串
buf 屬性是一個char類型的數組,最后一個字節保存了空字符“\0”
SDS遵循C字符串以空字符串結尾的慣例,保存空字符的1字節空間不計算在SDS的len屬性里,並為空字符分配額外的1字節空間,以及添加空字符到字符串末尾等操作,都是由SDS函數自動完成的,所以這個空字符對於SDS的使用者來說是完全透明的。
遵循空字符結尾的這一慣例的好處是,SDS可以直接重用一部分C字符串函數庫里的函數。
圖2.2展示了另一個SDS實例,這個SDSbuf數組分配了5個未使用空間,free屬性為5
二、SDS與C字符串區別
傳統C語言使用長度為N+1的字符數組來表示長度為N的字符串
C語言使用的這種簡單的字符串表示方式,並不能滿足Redis對字符串在安全性、效率以及功能方面的要求。
1.常數復雜度獲取字符串長度
2.杜絕緩沖區溢出
3.減少修改字符串時帶來的內存重分配次數
4.二進制安全
5.兼容部分C字符串函數