快速列表簡介
在Redis3 .2版本之前,儲存列表(list)資料結構使用的是壓縮列表(ziplist)和連結串列(linkedlist),當列表元素個數比較少並且每個元素佔用空間比較小的時候,使用壓縮列表。當列表元素個數比較多或者某個元素佔用空間比較大的時候,使用連結串列。
考慮到連結串列的附加空間相對太高,結點的記憶體也是單獨分配的,影響記憶體管理效率。在Redis3 .2版本開始對列表資料結構進行了改造,使用快速列表(quicklist)代替了壓縮列表(ziplist)和連結串列(linkedlist)。
快速列表(quicklist)是以壓縮列表(ziplist)為節點的連結串列(linkedlist),將連結串列按段切分,每一段使用壓縮列表進行記憶體的連續儲存,多個壓縮列表通過prev和next指標組成的雙向連結串列。它結合了壓縮列表和連結串列的優勢,進一步壓縮了記憶體的使用量,進一步提高了效率。
下面我們瞭解一下快速列表的具體實現。
快速列表的實現
在Redis中的快速列表是由quicklist
結構表示的,quicklist
結構包含由多個快速列表結點組成的雙向連結串列,每一個快速列表結點都儲存了一個壓縮列表。下面我們一個一個地詳細瞭解一下。
quicklist結構
快速列表是由quicklist
結構表示的,它包含以下幾個屬性:
head
屬性: 指向頭部快速列表結點的指標。tail
屬性:指向尾部快速列表結點的指標。count
屬性:在所有壓縮列表中元素的個數總和。len
屬性:快速列表結點的個數。fill
屬性:壓縮列表的最大大小,存放list-max-ziplist-size
引數的值。當超出了這個配置,就會新建一個壓縮列表。compress
屬性:結點壓縮深度,存放list-compress-depth
引數的值。bookmarks
屬性:用來快速列表重新分配記憶體空間時使用的陣列,不使用時不佔用空間。bookmark_count
屬性:bookmarks陣列的大小。
快速列表結點
快速列表結點使用quicklistNode
結構表示,它包含以下幾個屬性:
prev
屬性:指向前一個快速列表結點的指標。next
屬性:指向後一個快速列表結點的指標。zl
屬性:指向壓縮列表的指標,如果當前結點的資料被壓縮,那麼它指向一個quicklistLZF
結構。sz
屬性:壓縮列表的所佔位元組總數。count
屬性:壓縮列表中的元素數量。encoding
屬性:儲存形式,原生位元組陣列還是LZF壓縮儲存。recompress
屬性:當檢視了某一項被壓縮的資料時,需要把資料暫時解壓,這時就設定 recompress = 1 做一個標記,等有機會再把資料重新壓縮。
quicklistLZF結構
當快速列表結點資料被壓縮時,資料會被存放在quicklistLZF結構中,它包含以下幾個屬性:
sz
屬性:表示壓縮後的大小。compressed
屬性:存放壓縮後的位元組陣列。
快速列表的壓縮機制
在快速列表中,兩端結點的資料被訪問的可能性比較高,中間結點的資料被訪問的可能性比較低。如果我們的應用場景符合這個特點,可以把中間結點的資料使用 LZF 演算法進行壓縮,從而進一步節省記憶體空間。我們可以對list-compress-depth
引數進行配置。
預設情況下,list-compress-depth
引數為0,也就是不壓縮資料;當該引數被設定為1時,除了頭部和尾部之外的結點都會被壓縮;當該引數被設定為2時,除了頭部、頭部的下一個、尾部、尾部的上一個之外的結點都會被壓縮;當該引數被設定為2時,除了頭部、頭部的下一個、頭部的下一個的下一個、尾部、尾部的上一個、尾部的上一個的上一個之外的結點都會被壓縮;以此類推。
最後,謝謝你這麼帥,還給我點贊和關注。
微信公眾號:萬貓學社
微信掃描二維碼
關注後回覆「電子書」
獲取12本Java必讀技術書籍