Redis 原始碼解析 6 五大資料型別之字串

2022-02-13 19:11:29 字數 3176 閱讀 5580

前文 redis 設計與實現 2:redis 物件 說到,五大資料型別都會封裝成redisobject

typedef struct redisobject  robj;
不同資料型別的主要區別就是typeencoding屬性的差異,同一種資料型別,有不同的編碼。

字串的編碼有rawembstrint三種。

定義在server.h中,這裡只列出string型別的編碼

#define obj_encoding_raw 0

#define obj_encoding_int 1

#define obj_encoding_embstr 8

raw編碼主要用來儲存長度超過 44 的字串。其真實資料,由sdshdr結構來表示儲存,外層還是由 redisobject 包裝。

sdshdr的結構在前文 redis 設計與實現 3:字串 sds 中有講到。

sdshdr結構大致如下:

redisobject 中的ptr指標,就是指向sds

embstr編碼是專門用於儲存短字串的一種優化編碼方式。當字串的長度小於等於44的時候,將採用embstr編碼。

建立字串物件的**如下(object.c):

#define obj_encoding_embstr_size_limit 44

robj *createstringobject(const char *ptr, size_t len)

embstr有個顯著的特點,就是redisobjectsds的記憶體是挨在一起的。挨在一起的好處:

其結構示意圖如下:

embstr 問題一:那麼為什麼 embstr 跟 raw 的界限是44呢?

struct __attribute__ ((__packed__)) sdshdr8 ;
typedef struct redisobject  robj;
redisobject + sdshdr8至少需要3 + 16 = 19位元組。

redis 認為如果超過64位元組就是大字串,所以在redisobject+ sdshdr8的總長度是64位元組的情況下,留給buf的長度就只剩下45位元組,由於字串結尾需要乙個\0占用乙個位元組,所以留個字串的長度就只有44位元組了。

公式:64 - 3(sdshdr8) - 16(redisobject) - 1(\0) = 44

embstr 問題二:為什麼網上有的博文說 embstr 跟 raw 的界限是 39

在 redis 3.2 版本之前,這個界限的確是 39,為什麼後面改成 44 了呢?

那是因為sdshdr的結構在 3.2 版本的時候修改了。3.2 之前的sdshdr結構是:

struct sdshdr ;
舊版本的sdshdr的頭占用了 8 個位元組,比新版本的多了5個位元組,所以界限就是44 - 5 = 39啦!

如果乙個字串物件儲存的是整數值,並且這個整數值可以用long型別來表示,那麼這個整數值將會儲存在字串物件結構的ptr屬性裡面(將void*轉換成long),並將字串物件的編碼設定為int

相對於用raw編碼,int編碼既節省了指標占用的記憶體,也節省了sds結構的記憶體。

redis> set int_key 12345

okredis> object encoding int_key

"int"

下圖為存著12345string示例結構:

127.0.0.1:6379> set num 1

ok127.0.0.1:6379> object encoding num

"int"

(integer) 2

127.0.0.1:6379> object encoding num

"raw"

127.0.0.1:6379> set num 12

ok127.0.0.1:6379> object encoding num

"int"

一旦編碼變為raw之後,將不會再轉成embstr

本文的分析沒有特殊說明都是基於 redis 6.0 版本原始碼

redis 6.0 原始碼:

redis五大資料型別

redis支援五種資料型別 string 字串 hash 雜湊 list 列表 set 集合 及zset sorted set 有序集合 127.0 0.1 6379 set name yzl ok127.0 0.1 6379 get name yzl 127.0 0.1 6379 hmset my...

redis五大資料型別

string是redis最基本的型別 string型別是二進位制安全的,可以包含任何資料,或者序列化的物件 string型別是redis最基本的資料型別,乙個redis中字串value最多可以是512mhash是乙個鍵值對集合 hash是乙個string型別的field和value的對映表,hash...

redis五大資料型別

string是redis最基本的型別 string型別是二進位制安全的,可以包含任何資料,或者序列化的物件 string型別是redis最基本的資料型別,乙個redis中字串value最多可以是512mhash是乙個鍵值對集合 hash是乙個string型別的field和value的對映表,hash...