1. 程式人生 > 實用技巧 >redis 各種資料結構的encoding實現

redis 各種資料結構的encoding實現

redis 各種資料結構的encoding實現


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這樣設計有兩個好處:

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

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

  3. 這時候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"

————————————————————————————————
本文內容非本猿原創,只是在作者原文稍作修改。
————————————————————————————————
原文連結:https://blog.csdn.net/clypm/article/details/52312937