首頁  >  文章  >  資料庫  >  Redis壓縮列表的詳細介紹(範例講解)

Redis壓縮列表的詳細介紹(範例講解)

不言
不言轉載
2019-02-12 13:34:342504瀏覽

這篇文章帶給大家的內容是關於Redis壓縮清單的詳細介紹(範例講解),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

這篇文章是主要介紹Redis在資料儲存方面的其中一種方式,壓縮清單。

本文會介紹

1、壓縮清單(ziplist)的使用情境 

2.如何達到節省記憶體的效果?

3.壓縮清單的儲存格式 

#4. 連鎖更新的問題  

# . conf檔案配置。

在實務上的操作主要是對conf設定檔進行配置,具體上沒有確切的一個值,更多是經驗值。也有的項目會直接使用原本的預設值。此篇對於更能理解一個資料庫底層的儲存邏輯會有一點幫助。修學儲能,既要博,也要淵博。希望這篇文章對同樣也是在學習Redis的各位同伴有點用。 (推薦教程:

Redis教程

一、壓縮列表(ziplist)的使用場景:

Redis為了優化資料存儲,節省內存,在列表、字典(哈希鍵)和有序集合的底層實現了使用壓縮列表這一優化方案。

例如,假如一個哈希鍵裡面存儲的字串比較短,那麼Redis就會將它用壓縮列表的格式去存儲,即轉換為字節數組存儲。而一個雜湊鍵內部儲存的整數值比較小,同樣也會把它儲存為壓縮列表的一個節點。同理,列表鍵的對小資料的儲存跟哈希鍵的操作類似。

如此說來,壓縮列表並不是開發者可以直接呼叫的Redis中的一種儲存資料結構,而是Redis中為

優化資料儲存而在底層做的一項努力。理解好這點還是比較重要的。

二、如何達到節約記憶體的效果?

壓縮列表是一種序列化的資料結構,這種資料結構的功能是將一系列資料與其編碼資訊儲存在一塊連續的記憶體區域,這塊記憶體物理上是連續的。但邏輯上被分成多個組成部分,即節點。目的是為了在

一定可控的時間複雜度條件下盡可能的減少不必要的記憶體開銷,從而達到節省記憶體的效果。要理解是怎麼達到節約記憶體作用的,還需要去了解壓縮列表的儲存格式。

三、壓縮清單的儲存格式:

#壓縮清單(ziplist)是Redis清單鍵、雜湊鍵和有序集合鍵的底層實作之一,其實質是

一種序列化的資料儲存結構。有別於普通情況下,Redis以雙端鍊錶表示列表,使用散列表表示哈希鍵,用散列表 跳躍表表示有序集合。當一個列表或雜湊字典/有序集合只包含很少內容,並且每一個列表項或哈希項/有序集合項如果是小整數,或者比較短的字串。那麼Redis就會用壓縮列表來做底層的實作。

壓縮列表由一系列經Redis特殊編碼的

連續記憶體區塊

組成,每一個記憶體區塊稱為一個節點(entry),而一個壓縮列表可以包含很多個節點。每個節點儲存的資料格式可以是位元組數組(中文字串等都會轉換為位元組數組)或整數值。

位元組數組的長度可以是以下的其中一個:

1. 長度小於等於63位元組(2的6次方)

2. 長度小於等於16383位元組(2的14次方)

3. 長度小於等於4294967295位元組(2的32次方)

整數值可能是以下六種中的其中一種:

1. 4位元長,介於0-12之間的無符號整數

#2. 1位元組長的有符號整數

3. 3字節長的有符號整數

4. int16_t型別整數

5. int32_型別整數

6. int64_t型別整數

普通儲存格式下和壓縮清單儲存格式下的不同點:

清單儲存結構典型的為雙端鍊錶,每一個值都是用一個節點來表示,每個節點都會有指向前一個節點和後一個節點的指針,以及指向節點包含的字串值的指針。而字串值又分為3個部分存儲,第一部分儲存字串長度,第二部分儲存字串值中剩餘可用的位元組量,第三部分儲存的則是字串資料本身。所以一個節點往往都需要儲存3個指標、2個記錄字串資訊的整數、字串本省和一個額外的位元組。整體上額外的開銷是很大的(21位元組)。

壓縮清單節點的格式:

##########

每個節點都有previous_entry_length,encoding,content三個部分組成,在遍歷壓縮列表的時候是從後往前遍歷的。

1. previous_entry_length記錄了前一個節點的長度,只要用目前指標減去這個值就可以達到前一個節點的起始位址。

2. encoding記錄了節點content屬性所保存資料的型別與長度

3. content記錄了一個節點的值

顯然壓縮列表這種方式節省了不少儲存空間。但同時也會引發下面的問題。

四、連鎖更新的問題:

#一般而言如果前一個節點的整體長度小於254位元組,previous_entry_length屬性只需要1個位元組的空間來保存這個長度值。而當前一個節點大於254位元組的時候,previous_entry_length屬性要用5個位元組長的空間來記錄長度值。

當長度為254位元組左右的節點前插入一個新的節點的時候,需要增加previous_entry_length來記錄這個節點到新節點的偏移量。這時候,這個節點的長度一定就大於254位元組了。所以這個節點的後一個節點就不能只用一個位元組的previous_entry_length來記錄這個節點的資訊了,而是需要5個位元組來記錄。如果連續多個節點的長度都為254位元組左右,在其中的某一個節點前/後發生節點的插入和刪除(刪除的推理與插入相反,原本用5位元組記錄前一節點的可能變為1位元組),都可能引發連鎖的更新,顯然,這樣對系統地運作效率是很不利的。不過,在實際應用中這種情況還是比較少發生的。

而雙端鍊錶在節點的更新、增加和刪除上顯得會「輕鬆」很多了。因為每一個節點所儲存的資訊都是相對獨立的。

實務意義:

要預估一個節點大概佔據多少位元組的儲存空間,適當地調整欄位的儲存格式而不要使儲存的欄位值佔據儲存空間落在254字節(除去encoding屬性和previous_entry_length屬性)左右。

Redis中檢視字串和雜湊鍵值的長度相關指令:

1. 查詢字串鍵對應的值長度

指令:

Strlen

例如:

127.0.0.1:6379> strlen m_name

#(integer) 8

2. 查詢雜湊鍵某一個網域長度

指令:

Hstrlen

例如:

127.0.0.1:6379> hstrlen good_list good_list1

(integer) 226

五、Conf檔案設定:

##透過修改設定檔,可以控制

是否使用壓縮清單儲存相關鍵的最大元素個數和最大元素的大小##Conf檔案中的配置:

1.


[] -max-ziplist-entries : 表示對於鍵的最大元素個數,即一個鍵中在該指定值下的數量的節點個數都會用壓縮列表來儲存

[] -max-ziplist-value :表示壓縮列表中每個節點的最大體積是多少字節

#實際使用中,一個列表鍵/哈希鍵的某一個元素往往存儲著比較大的資訊量,會大於64位元組,所以配置時很有可能會比64大,同時考慮到實際儲存資料的容量大小以及上面談到的previous_entry_length的大小問題,對[] -max-ziplist-value進行合理的配置。

設定檔內容:

############## ADVANCED CONFIG ##########################
哈希键
# Hashes are encoded using a memory efficient data structure when they have a
# small number of entries, and the biggest entry does not exceed a given
# threshold. These thresholds can be configured using the following directives.
hash-max-ziplist-entries 512
hash-max-ziplist-value 64

有序集合键
# Similarly to hashes and lists, sorted sets are also specially encoded in
# order to save a lot of space. This encoding is only used when the length and
# elements of a sorted set are below the following limits:
zset-max-ziplist-entries 128
zset-max-ziplist-value 64

列表键,比较特殊,直接使用制定大小kb字节数表示(有些conf文件的列表键与hash键的表达式没太大区别)
# Lists are also encoded in a special way to save a lot of space.
# The number of entries allowed per internal list node can be specified
# as a fixed maximum size or a maximum number of elements.
# For a fixed maximum size, use -5 through -1, meaning:
# -5: max size: 64 Kb  <-- not recommended for normal workloads
# -4: max size: 32 Kb  <-- not recommended
# -3: max size: 16 Kb  <-- probably not recommended
# -2: max size: 8 Kb   <-- good
# -1: max size: 4 Kb   <-- good
# Positive numbers mean store up to _exactly_ that number of elements
# per list node.
# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size),
# but if your use case is unique, adjust the settings as necessary.
list-max-ziplist-size -2

案例:

修改設定前使用預設設定:

hash-max-ziplist-entries 512

hash-max-ziplist-value 64

127.0.0.1:6379> hstrlen good_list good_list1

(integer) 226

127.0.0.1:6379>object list

"hashtable"

修改設定:

hash-max-ziplist-entries 512

hash-max-ziplist-value 254

注意:修改設定後需要重新啟動伺服器

127.0.0.1:6379> hstrlen good_list good_list1

#(integer) 226

127.0.0.1 :6379> object encoding good_list

"ziplist"

可以看到儲存方式已將變為ziplist

較官方的壓力測試和指導建議:

當一個壓縮列表的元素數量上升到幾千(實際使用可能遠小於這個值)的時候,壓縮列表的性能可能會下降,因為Redis在操作這種結構的時候,編解碼會出現一定的壓力。

壓縮清單的長度限制在500-2000之內,每個元素體積限制在128位元組或以下,壓縮清單的的效能都會處於合理範圍之內。

以上是Redis壓縮列表的詳細介紹(範例講解)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:cnblogs.com。如有侵權,請聯絡admin@php.cn刪除