Redis閱讀筆記-列表物件
Redis閱讀筆記-列表物件
列表物件的編碼可以是ziplist或linkedlist。
ziplist編碼的列表物件使用壓縮表作為底層實現, 每個壓縮表節點(entry)儲存了一個列表元素。 舉個例子, 若我們執行rpush命令, 那麼伺服器將建立一個列表物件作為numbers鍵的值:
127.0.0.1:6379> rpush numbers 1 3 5
(integer) 3
如果numbers鍵的值物件使用的是ziplist編碼, 這個值物件將會是下圖所展示的樣子。
redisObject | ||||||||
type REDIS_LIST | ||||||||
encoding REDIS_ENCODING_ZIPLIST |
||||||||
ptr | → | zlbytes | zltail | zllen | 1 | 3 | 5 | zlend |
... |
另一方面,linkedlist編碼的列表物件使用雙端連結串列作為底層實現,每個雙端連結串列節點(node)都儲存了一個字串物件, 而每個字串物件都儲存了一個列表元素。
舉個例子, 如果前面所說的numbers鍵建立的列表物件使用的是ziplist編碼, 而是linkedlist編碼, 那麼numbers鍵的值物件將是下圖的樣子。
redisObject | ||||||
type REDIS_LIST | ||||||
encoding REDIS_ENCODING_LINKEDLIST | ||||||
ptr | → | StringObject 1 |
→ | StringObject 3 |
→ | StringObject 5 |
... |
注意,linkedlist編碼的列表物件再底層的雙端連結串列結構中包含了多個字串物件, 這種巢狀字串物件的行為在稍後介紹的好戲物件、集合物件和有序集合物件中都會出現,字串物件是Redis五種型別的物件中唯一 一種會被其他四種類型物件巢狀的物件。
編碼轉換
當列表物件可以同時滿足以下兩個條件時, 列表物件使用ziplist編碼:
- 列表物件儲存的所有字串元素的長度都小於64位元組
- 列表物件儲存的元素數量小於512個;不能滿足這兩個條件的列表物件需要使用linkedlist編碼。
以上兩個條件的上限值是可以修改的, 具體請看配置檔案中關於list-max-ziplist-value
選項和list-max-ziplist-entries
選項說明。
對於使用ziplist編碼的列表物件來說, 當使用ziplist編碼所需要的兩個條件的任意一個不能被滿足時, 物件的編碼轉換操作就會被執行,原本儲存在壓縮列表裡的所有列表元素都會被轉移並儲存到雙端連結串列裡, 物件的編碼也會從ziplist變成linkedlist。
以下程式碼展示了列表物件因為儲存長度太大的元素而進行編碼轉換的情況:
# 所有元素的長度都小於64位元組
127.0.0.1:6379> rpush blah 'hello' 'world' 'again'
(integer) 3
127.0.0.1:6379> object encoding blah
"ziplist"
# 將一個65位元組長的元素推入列表物件中
127.0.0.1:6379> rpush blah 'wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww'
(integer) 4
# 編碼已改變
127.0.0.1:6379> object encoding blah
"linkedlist"
除此之外, 以下程式碼展示了列表物件因為儲存元素數量過多而進行編碼轉換的情況:
127.0.0.1:6379> EVAL "for i = 1, 512 do redis.call('RPUSH', KEYS[1], i) end" 1 integers
(nil)
127.0.0.1:6379> llen integers
(integer) 512
127.0.0.1:6379> object encoding integers
"ziplist"
127.0.0.1:6379> rpush integers 513
(integer) 513
127.0.0.1:6379> object encoding integers
"linkedlist"