Redis知識總結--string的內部實現
阿新 • • 發佈:2018-12-03
SDS(Simple Dynamic String)
String的資料結構是一個位元組陣列,但簡單的獲取陣列長度的時間複雜度就是O(n),這對於單執行緒的redis來講是不能接受的,因此string在redis中的實現是SDS類,SDS類的結構總體如下(C已忘,只能用java大致表達下):
public class SDS { // string內容的真實長度,為了節約記憶體,這裡是個泛型 // 當內容較少時,使用byte或short private T length; // 為string分配的記憶體空間大小,同樣為了節約記憶體,用了泛型 private T capacity; // string的真實內容,使用位元組陣列儲存 private byte[] content; // 特殊標記,不知道幹嘛的 private byte flags; }
如上,長度直接儲存下來了--雖然兩者沒什麼關聯,但我想到了mysql的Myisam引擎,也是直接將表的資料條數直接儲存下來--這樣要獲取長度直接取值即可;
embded 和 RAW
使用debug object命令會發現,不同長度的string的encoding有embed和raw兩種型別,也是為了節省空間,64位元組及以下的string會使用embed儲存,以上使用RAW儲存(不同redis版本下可能會有不同的界限),之所以使用64為界是因為記憶體分配函式malloc等都是一次分配2的若干次冪大小的記憶體,另外即使分配64位元組給string使用,content也只有44位元組的記憶體可以儲存,原因正是因為下面的redis頭物件也佔了坑
RedisObject
public class RedisObject {
// 資料型別,只使用4bit
private int4 type;
// 資料的encoding型別,只使用4bit
private int4 encoding;
// 資料的lru資訊,只使用24bit
private int24 lru;
// 該資料的引用計數,使用32bit
private int32 refcount;
// 這是個指標,指向資料物件,在64位作業系統下,使用8個位元組
private Poniter *p;
}
可以發現,物件頭至少使用16個位元組,而假使SDS的三個輔助屬性都只使用1位元組的話,content也就只剩下64-19=45位元組的空間可以使用了,還有一個位元組用來儲存字串的結尾字元,這個字元通常使用的是null,而在redis中使用的是\0,\0使用了1個位元組,content的可用有效字元就僅剩44位元組了