redis之string原始碼分析

2021-09-25 04:05:37 字數 3023 閱讀 9195

string資料型別的物件編碼有兩種,分別是embstrraw。兩種編碼的區別並不大,embstr相對於raw,記憶體空間連續。兩者的資料格式見下圖:

redis的string資料之所以使用embstrraw兩種編碼格式,是為了當乙個string物件的值比較小時,使用乙個連續的記憶體分割槽存放redisobject物件和sdshdr物件,減少記憶體分配和**的消耗。

embstr編碼的string資料只需要建立分配乙個記憶體空間,用於同時存放redisobject物件和sdshdr物件;而raw編碼的string資料需要建立兩個記憶體空間分別存放redisobject物件與sdshdr物件,相對於embstr編碼多了一次記憶體分配和一次記憶體**的消耗。

當乙個string物件的長度達到臨界值時,就會觸發編碼轉換,該臨界值是string值長度:44。

如下測試,當string值的長度不大於44時,通過debug命令輸出該string物件的編碼格式為encoding:embstr;當string值的長度大於44時,編碼格式則為encoding:raw

127.0.0.1:6379> set key1 12345678901234567890123456789012345678901234

ok127.0.0.1:6379> debug object key1

value at:0x7f8428e22080 refcount:1 encoding:embstr serializedlength:21 lru:2200798 lru_seconds_idle:6

127.0.0.1:6379> set key2 123456789012345678901234567890123456789012345

ok127.0.0.1:6379> debug object key2

value at:0x7f8428eb3490 refcount:1 encoding:raw serializedlength:21 lru:2200816 lru_seconds_idle:3

關鍵原始碼如下:

#define obj_encoding_embstr_size_limit 44

robj *

createstringobject

(const

char

*ptr, size_t len)

robj *

tryobjectencoding

(robj *o)..

.}

embstr
robj *

createembeddedstringobject

(const

char

*ptr, size_t len)

else

sh->len = len;

sh->alloc = len;

sh->flags = sds_type_8;

if(ptr == sds_noinit)

sh->buf[len]

='\0'

;else

if(ptr)

else

return o;

}

raw
robj *

createrawstringobject

(const

char

*ptr, size_t len)

robj *

createobject

(int type,

void

*ptr)

else

return o;

}

臨界值44

之所以embstrraw兩種編碼格式的臨界值是44,是因為redis控制乙個string物件的記憶體大小不大於64位元組時為乙個小字串,使用乙個連續空間能夠提高效能。當string物件的記憶體大小大於64位元組時,則認為是乙個大字串,不再適用embstr編碼格式,而使用raw編碼。

由圖可見,redisobject物件和sdshdr物件至少需要佔19位元組,64個位元組空間最後留給string值的只有45個位元組。而string末尾需要額外乙個\0表示字串結束,所以實際上留給string值最多只有44個位元組。

redis的string物件直接通過set等方法建立時,不會建立冗餘空間,因為大多數情況下建立的string型別不需要進行追加擷取等操作。

擴容規則

通過預先建立冗餘空間,可以減少string資料追加擷取時的記憶體空間分配消耗。

sds sdscatlen

(sds s,

const

void

*t, size_t len)

#define sds_max_prealloc (1024*1024)

sds sdsmakeroomfor

(sds s, size_t addlen)

else

sdssetalloc

(s, newlen)

;return s;

}

原始碼分析之String

先看屬性 底層是char陣列,一目了然 可以看到,value是儲存string的內容的,即當使用string str abc 的時候,本質上,abc 是儲存在乙個char型別的陣列中的。string底層的儲存結構是乙個字元型別的陣列,同樣也是被final修飾,因此一旦這個字元陣列被建立後,value...

golang 原始碼分析之string

stringgo 語言中的字串其實是乙個唯讀的位元組陣列string 對應的結構 type stringheader struct type stringstruct struct 字串拼接 concatstrings runtime concatstrings func concatstrings...

redis原始碼之dict

大家都知道redis預設是16個db,但是這些db底層的設計結構是什麼樣的呢?我們來簡單的看一下原始碼,重要的字段都有所注釋 typedef struct redisdb redisdb redis中的所有kv都是存放在dict中的,dict型別在redis中非常重要。字典disc的資料結構如下 t...