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