Redis系列(八)底層數據結構之緊湊列表

前言

Redis 已是你們耳熟能詳的東西了,平常工做也都在使用,面試中也是高頻的會涉及到,那麼咱們對它究竟瞭解有多深入呢?面試

我讀了幾本 Redis 相關的書籍,嘗試去了解它的具體實現,將一些底層的數據結構及實現原理記錄下來。後端

本文將介紹 Redis 中底層的 listpack(緊湊列表) 的實現方法。 它是 Redis 的 Stream 用到的數據結構之一。數組

定義

Redis 設計 listpack 的目的就是取代 ziplist, 在 Redis 系列(三)底層數據結構之壓縮列表 中咱們提到,ziplist 在極小的機率下有可能發生級聯更新,當連續規模較大的級聯更新發生時,對 Redis 的性能有比較大的影響。微信

雖然咱們都知道這是極小的機率,可是這種設計缺陷卻不能被 Redis 的大佬做者所接受,所以在 5.0 版本中新引入了一個數據結構,名叫 listpack, 你們都將它翻譯爲 緊湊列表.數據結構

它的定義和 ziplist 極其類似,只是經過一些新的設計,來解決 ziplist 中的痛點問題。所以本文的講解基於讀者已經瞭解 ziplist.性能

ziplist的定義以下: 注意:這是 ziplist 的定義學習

struct ziplist<T>{
    // 整個壓縮列表佔用字節數
    int32 zlbytes;
    // 最後一個節點到壓縮列表起始位置的偏移量,能夠用來快速的定位到壓縮列表中的最後一個元素
    int32 zltail_offset;
    // 壓縮列表包含的元素個數
    int16 zllength;
    // 元素內容列表,用數組存儲,內存上緊挨着
    T[] entries;
    // 壓縮列表的結束標誌位,值永遠爲 0xFF.
    int8 zlend;
}
複製代碼

listpack 的定義和上方基本一致,只是去掉了 zltail_offset 屬性。url

讓咱們回想一下,ziplist 中用這個屬性作什麼?用來方便的找到最後一個節點,而後方便進行反向的遍歷。新的 listpack 固然是解決了這個問題,才能放心的刪除掉這個屬性。spa

listpack節點的定義以下:翻譯

int<var> encoding;
optional byte[] content;
int<var> length;
複製代碼

相比於 ziplist 的定義,它有兩點改動:

  1. 記錄的長度再也不是前一個節點的長度,而是本身的長度。
  2. 將記錄本身的長度放到了節點的尾部。

這樣作的好處是:

  1. 再也不須要 zltail_offset 屬性也能夠快速定位到最後一個節點。用listpac 的總長度-最後一個節點的長度.
  2. 每一個節點記錄本身的長度,當本節點的值發生了改變,只須要更改本身的長度便可。再也不須要更改別的節點的屬性,也就完全的解決掉了級聯更新問題。

總結

listpack 是 Redis 設計用來取代掉 ziplist 的數據結構,它經過每一個節點記錄本身的長度,且放在節點的尾部,來完全解決掉了 ziplist 存在的級聯更新的問題。

listpack 在 5.0 版本引入,可是因爲 ziplist 在 Reids 內部的使用太過於普遍,有一些兼容問題,咱們能夠預見這將是一個逐步的替換過程。

一樣在 5.0 版本引入的 Stream 數據結構中,就使用了 listpack 而不是 ziplist.

參考文章

《Redis 的設計與實現(第二版)》

《Redis 深度歷險:核心原理和應用實踐》

完。

聯繫我

最後,歡迎關注個人我的公衆號【 呼延十 】,會不按期更新不少後端工程師的學習筆記。 也歡迎直接公衆號私信或者郵箱聯繫我,必定知無不言,言無不盡。


以上皆爲我的所思所得,若有錯誤歡迎評論區指正。

歡迎轉載,煩請署名並保留原文連接。

聯繫郵箱:huyanshi2580@gmail.com

更多學習筆記見我的博客或關注微信公衆號 < 呼延十 >------>呼延十

相關文章
相關標籤/搜索