redis 各種資料結構的encoding實現

2022-03-13 01:44:42 字數 4494 閱讀 4822

redis 各種資料結構的encoding實現

redis type命令實際返回的就是當前鍵的資料結構型別,它們分別是:string(字串)、hash(雜湊)、list(列表)、set(集合)、zset(有序集合),但這些只是redis對外的資料結構。

我們可以通過object encoding命令查詢內部編碼:
127.0.0.1:6379> set set:1 hello

ok127.0.0.1:6379> object encoding set:1

"embstr"

127.0.0.1:6379> hset user:1 name kebi

(integer) 1

127.0.0.1:6379> object encoding user:1

"ziplist"

可以看到鍵set:1對應值的內部編碼是「embstr」,鍵user:1對應值的內部編碼是「ziplist」。

redis這樣設計有兩個好處:

第一,可以改進內部編碼,而對外的資料結構和命令沒有影響,這樣一旦開發開發出優秀的內部編碼,無需改動外部資料結構和命令。

第二,多種內部編碼實現可以在不同場景下發揮各自的優勢。例如ziplist比較節省記憶體,但是在列表元素比較多的情況下,效能會有所下降,

這時候redis會根據配置選項將列表型別的內部實現轉換為linkedlist。

下面會分別介紹5種資料結構的內部編碼方式。

1.字串的內部編碼

字串型別的內部編碼有3種:

int:8個位元組的長整型。

embstr:小於等於39個位元組的字串。

raw:大於39個位元組的字串。\

(1)整數型別示例如下:
127.0.0.1:6379> set str 1234567 

ok127.0.0.1:6379> object encoding str

"int"

(2)短字串示例如下:

127.0.0.1:6379> set str "hello world"

ok127.0.0.1:6379> object encoding str

"embstr"

(3)長字串示例如下:

127.0.0.1:6379> set str "tranquil,unbeatable to the outside. -- yangming"  #「凝聚於內,無敵於外。--王陽明」

ok127.0.0.1:6379> object encoding str

"raw"

2.雜湊的內部編碼

雜湊型別的內部編碼有兩種:

(1)當field個數比較少且沒有大的value時,內部編碼為ziplist:
127.0.0.1:6379> hmset user:2 name kebi age 26

ok127.0.0.1:6379> object encoding user:2

"ziplist"

(2)當有value大於64個位元組,內部編碼會由ziplist變為hashtable:

127.0.0.1:6379> hmset user:1 info "沐春風,惹一身紅塵;望秋月,化半縷輕煙。顧盼間乾坤倒轉,一霎時滄海桑田。方曉,彈指紅顏老,剎那芳華逝。"

127.0.0.1:6379> object encoding user:1

"hashtable"

(3)當field個數超過512,內部編碼也會由ziplist變為hashtable:

...待插入內容...

注意:當乙個雜湊的編碼由ziplist變為hashtable的時候,即使在替換掉所有值,它一直都會是hashtable型別。

3.列表的內部編碼
列表型別的內部編碼有兩種:

ziplist(壓縮列表):當雜湊型別元素個數小於hash-max-ziplist-entries配置(預設512個)

同時所有值都小於hash-max-ziplist-value配置(預設64個位元組)時,redis會使用ziplist作為雜湊的內部實現。\

linkedlist(鍊錶):當列表型別無法滿足ziplist的條件時,redis會使用linkedlist作為列表的內部實現。

(1)當元素個數較少且沒有大元素時,內部編碼為ziplist:
127.0.0.1:6379> rpush list:2 a b c

(integer) 3

127.0.0.1:6379> object encoding list:2

"ziplist"

(2)當元素個數超過512個,內部編碼變為linkedlist:

127.0.0.1:6379>lpush setkey 1 2 3 ... 513

ok127.0.0.1:6379> object encoding listkey

"linkedlist"

(3)當某個元素超過64個位元組,內部編碼也會變為linkedlist:

127.0.0.1:6379> rpush list:1 a b "我不再說話,不再思索,但無盡的愛從靈魂中公升起,我將遠行,走得很遠,如同乙個吉普塞人,穿過大自然——幸福得如有一位女子同行。"

(integer) 6

127.0.0.1:6379> object encoding list:1

"linkedlist"

- #只能公升級,不能自動變回ziplist型別

4.集合的內部編碼

集合型別的內部編碼有兩種:

intset(整數集合):當集合中的元素都是整數且元素個數小於set-max-intset-entries配置(預設512個)時,

redis會選用intset來作為集合內部實現,從而減少記憶體的使用。

hashtable(雜湊表):當集合型別無法滿足intset的條件時,redis會使用hashtable作為集合的內部實現。

(1)當元素個數較少且都為整數時,內部編碼為intset:
127.0.0.1:6379> sadd setkey 2 3 4 5

(integer) 4

127.0.0.1:6379> object encoding setkey

"intset"

(2)當元素個數超過512個,內部編碼變為hastable:

127.0.0.1:6379>sadd setkey2 1 2 3 4 5 6 7...  511 512 513

ok127.0.0.1:6379> object encoding setkey2

"hashtable"

(3)當某個元素不為整數時,內部編碼也會變為hashtable:

127.0.0.1:6379> sadd setkey3 a b c

(integer) 3

127.0.0.1:6379> object encoding setkey2

"hashtable"

5.有序集合的內部編碼

有序集合型別的內部編碼有兩種

ziplist(壓縮列表):當有序集合的元素個數小於zset-max-ziplist-entries配置(預設128個)

同時每個元素的值小於zset-max-ziplist-value配置(預設64個位元組)時,redis會用ziplist來作為有序集合的內部實現,ziplist可以有效減少記憶體使用。

skiplist(跳躍表):當ziplist條件不滿足時,有序集合會使用skiplist作為內部實現,因為此時zip的讀寫效率會下降。

(1)當元素個數較少且每個元素較小時,內部編碼為ziplist:
127.0.0.1:6379> zadd zsetkey 50 a 60 b 30 c

(integer) 3

127.0.0.1:6379> object encoding zsetkey

"ziplist"

(2)當元素個數超過128個,內部編碼變為skiplist:

...待輸入...

(3)當某個元素大於64個位元組時,內部編碼也會變為skiplist:

127.0.0.1:6379> zadd zsetkey 50 a 60 b 30 '閃爍的太陽已越過高傲的山巒,幽谷中的光點有若泡沫浮起。'

(integer) 1

127.0.0.1:6379> object encoding zsetkey

"skiplist"

Redis入門 各種資料結構

string 型別 儲存形式 以 key value 形式存在 常用命令 set get del incr incr setnx list 型別 儲存形式 以 key 集合 形式存在 常用命令 rpush lpush llen lrange lpop rpop set 型別 儲存形式 以 key 集...

redis 各種資料結構的encoding實現

redis 各種資料結構的encoding實現 redis type命令實際返回的就是當前鍵的資料結構型別,它們分別是 string 字串 hash 雜湊 list 列表 set 集合 zset 有序集合 但這些只是redis對外的資料結構。我們可以通過object encoding命令查詢內部編碼...

Redis 各種資料結構記憶體占用測試

啟動時 redis為空 插入資料量都為100w 100w個key或者list中100w個值,或者1000個key,每個key中1000個值 key value如下 設定 ziplist中允許的條目個數 hash max ziplist entries 512 ziplist中每個條目 k v 的v允...