Redis的五種數據結構的內部編碼


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
OK
127.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個字節的字符串。

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

(1)整數類型示例如下:

127.0.0.1:6379> set str 1234567 
OK
127.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"  #“凝聚於內,無敵於外。--王陽明”
OK
127.0.0.1:6379> object encoding str
"raw"

 

2.哈希的內部編碼

哈希類型的內部編碼有兩種:

  • ziplist(壓縮列表):當哈希類型元素個數小於hash-max-ziplist-entries配置(默認512個),

    同時所有值都小於hash-max-ziplist-value配置(默認64個字節)時,Redis會使用ziplist作為哈希的內部實現

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

  • hashtable(哈希表):當哈希類型無法滿足ziplist的條件時,Redis會使用hashtable作為哈希的內部實現。

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

下面演示哈希類型的內部編碼,及相應的變化。

(1)當field個數比較少且沒有大的value時,內部編碼為ziplist:

127.0.0.1:6379> hmset user:2 name kebi age 26
OK
127.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
OK
127.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
OK
127.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"

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM