Redis的五種資料結構的內部編碼

2022-03-14 01:08:34 字數 4601 閱讀 9191

type命令實際返回的就是當前鍵的資料結構型別,它們分別是:string(字串)、hash(雜湊)、

list(列表)、set(集合)、zset(有序集合),但這些只是redis對外的資料結構。

實際上每種資料結構都有自己底層的內部編碼實現,而且是多種實現,這樣redis會在合適的場景選擇合適的內部編碼。

可以看到每種資料結構都有兩種以上的內部編碼實現,例如string資料結構就包含了raw、int和embstr三種內部編碼。

同時,有些內部編碼可以作為多種外部資料結構的內部實現,例如ziplist就是hash、list和zset共有的內部編碼。

我們可以通過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)

1127.0.0.1:6379> object encoding user:1

"ziplist

"

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

redis這樣設計有兩個好處:

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

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

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

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

1.字串的內部編碼

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

redis會根據當前值的型別和長度決定使用內部編碼實現。

(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"ok

127.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.雜湊的內部編碼雜湊型別的內部編碼有兩種:

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

ziplist使用更加緊湊的結構實現多個元素的連續儲存,所以在節省記憶體方面比hashtable更加優秀。

因為此時ziplist的讀寫效率會下降,而hashtable的讀寫時間複雜度為o(1)。

下面演示雜湊型別的內部編碼,及相應的變化。

(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.列表的內部編碼

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

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

下面演示列表型別的內部編碼,以及相應的變化:

(1)當元素個數較少且沒有大元素時,內部編碼為ziplist:

127.0.0.1:6379> rpush list:2

a b c

(integer)

3127.0.0.1:6379> object encoding list:2

"ziplist

"

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

127.0.0.1:6379>lpush setkey 1

23 ... 513

ok127.0.0.1:6379> object

encoding listkey

"linkedlist

"

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

127.0.0.1:6379> rpush list:1 a b "

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

"(integer)

6127.0.0.1:6379> object encoding list:1

"linkedlist

"

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

4.集合的內部編碼

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

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

下面用示例來說明:

(1)當元素個數較少且都為整數時,內部編碼為intset:

127.0.0.1:6379> sadd setkey 234

5(integer)

4127.0.0.1:6379> object

encoding setkey

"intset

"

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

127.0.0.1:6379>sadd setkey2 123

4567... 511

512513

ok127.0.0.1:6379> object

encoding setkey2

"hashtable

"

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

127.0.0.1:6379>sadd setkey3 a b c

(integer)

3127.0.0.1:6379> object

encoding setkey2

"hashtable

"

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

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

下面用示例來說明:

(1)當元素個數較少且每個元素較小時,內部編碼為ziplist:

127.0.0.1:6379> zadd zsetkey 50 a 60 b 30

c(integer)

3127.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)

1127.0.0.1:6379> object

encoding zsetkey

"skiplist

"

redis的五種資料結構

key 都是字串 value 五種資料結構 常用命令 常用命令 新增 lpush key value 將元素加入列表左邊 rpush key value 將元素加入列表右邊 獲取 lrange key start end 獲取範圍 刪除 lpop key 刪除列表最左邊的元素,並將元素返回 rpop...

Redis的五種資料結構

redis支援持久化只是它的一件 它提供了多達5種資料儲存方式 string是最簡單的型別,你可以理解成與memcached一模一樣的型別,乙個key對應乙個value,其上支援的操作與memcached的操作類似。但它的功能更豐富。list是乙個鍊錶結構,主要功能是push pop 獲取乙個範圍的...

Redis五種資料結構

redis除了儲存鍵之外還可以儲存常見的5種資料型別,分別是 string list set zset hash。結構型別 結構儲存的值 結構的讀寫能力 string字串 可以是字串 整數或浮點數 對整個字串或字串的一部分進行操作 對整數或浮點數進行自增或自減操作 list列表 乙個鍊錶,鍊錶上的每...