日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

《Redis核心技术与实战》学习总结(2)

發(fā)布時間:2023/12/4 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Redis核心技术与实战》学习总结(2) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

【Redis| 總結(jié)/Edison Zhou

1上一篇的遺留問題

上一篇總結(jié)了一個KV數(shù)據(jù)庫的基本架構(gòu) 和 Redis的底層數(shù)據(jù)結(jié)構(gòu)概覽,重點總結(jié)了Sorted Set的兩個數(shù)據(jù)結(jié)構(gòu)的切換,但沒有介紹List的兩個數(shù)據(jù)結(jié)構(gòu)的切換,因此本文試著總結(jié)一下。

這里先直接給出答案:


從上圖可以看到,當(dāng)List的數(shù)據(jù)滿足下面兩個條件時,就會使用壓縮列表,否則使用雙向鏈表。

(1)列表對象保存的所有字符串元素的長度都小于64字節(jié);

(2)列表對象保存的元素數(shù)量小于512個;

這兩個參數(shù)其實也是可以在redis.conf中修改的:

list-max-ziplist-value 64 list-max-ziplist-entries 512

2Redis 3.2之前的實現(xiàn)

由上一篇已經(jīng)知道,List類型的底層實現(xiàn)包括了 雙向鏈表 和?壓縮列表,但這是在Redis的3.2版本之前的底層實現(xiàn)。而從Redis 3.2版本開始,Redis修改了List的底層實現(xiàn),將壓縮列表 和 雙向鏈表 結(jié)合,我們稱它為 quickList 快速列表。

從第一節(jié)的內(nèi)容我們已經(jīng)知道,當(dāng)創(chuàng)建一個新的List時,Redis會優(yōu)先使用壓縮列表,然后在有需要的時候,再轉(zhuǎn)成雙向鏈表

Redis為什么要這么設(shè)計呢?

因為,雙向鏈表的內(nèi)存占用 比 壓縮列表?多,而壓縮列表的設(shè)計初衷就在于 節(jié)約內(nèi)存。眾所周知,Redis之所以快的原因之一就是它是內(nèi)存數(shù)據(jù)庫,所有操作都在內(nèi)存上完成,因此對于內(nèi)存的占用有要求。

雙向鏈表

壓縮列表

畫外音:在Redis 3.2 之前,我們也可以通過命令來驗證:

192.168.80.100:6379>?rpush?testkey?"edison"?"andy"?"leo" 3 192.168.80.100:6379> object encoding testkey ziplist 192.168.80.100:6379> rpush testkey "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww" 4 192.168.80.100:6379> object encoding testkey linkedlist

那么,壓縮列表為什么占用內(nèi)存少呢?

其實從上面的圖和下面的源碼也可以看出來,壓縮列表并沒有維護雙向指針prev 和 next,而只是存儲了上一個entry的長度 和 下一個entry的長度,通過長度來推算下一個entry在哪里。

typedef struct zlentry { // 壓縮列表節(jié)點unsigned int prevrawlensize, prevrawlen; // prevrawlen是前一個節(jié)點的長度,prevrawlensize是指prevrawlen的大小,有1字節(jié)和5字節(jié)兩種unsigned int lensize, len; // len為當(dāng)前節(jié)點長度 lensize為編碼len所需的字節(jié)大小unsigned int headersize; // 當(dāng)前節(jié)點的header大小unsigned char encoding; // 節(jié)點的編碼方式unsigned char *p; // 指向節(jié)點的指針 }?zlentry;

這是一種典型的“時間換空間”的方法,即犧牲讀取的性能,換取極致的存儲空間。由于壓縮列表存儲在一段連續(xù)的內(nèi)存上,所以它的存儲效率還是蠻高的。

但是,此種設(shè)計只適合在字段個數(shù)、值比較小的時候,一旦長度過長,壓縮列表的設(shè)計(利于讀取但不利于修改的初衷)會導(dǎo)致修改和刪除操作需要頻繁的申請和釋放內(nèi)存,可能會導(dǎo)致大量的數(shù)據(jù)拷貝,拖慢Redis的整體性能

因此,Redis選擇了在達(dá)到閾值時,切換數(shù)據(jù)結(jié)構(gòu)為雙向鏈表。

3Redis 3.2之后的實現(xiàn)

在Redis 3.2及之后,Redis選擇了結(jié)合壓縮列表 和 雙向鏈表的優(yōu)點,形成了一個新的底層實現(xiàn):quicklist 快速列表。

快速列表是一個壓縮列表組成的雙向鏈表,每個節(jié)點使用壓縮列表來保存數(shù)據(jù)。換句話說,快速列表中保存了一個個小的壓縮列表。其結(jié)構(gòu)如下圖所示:

為了進一步節(jié)約空間,Redis 還會對壓縮列表進行壓縮存儲(一種無損壓縮算法LZF),這取決壓縮深度的參數(shù)設(shè)置,我們可以選擇不壓縮(默認(rèn)值不壓縮)?也可以 選擇壓縮中間節(jié)點。

畫外音:兩端節(jié)點一般不被壓縮,因為當(dāng)一個鏈表很長時,最頻繁訪問的就是兩端的數(shù)據(jù),根據(jù)“二八定律”,兩端數(shù)據(jù)不壓縮,而將中間數(shù)據(jù)壓縮,從而節(jié)省空間,但又保證讀取效率。

此外,對于每個壓縮列表的大小,也是可以通過在redis.conf中的參數(shù)來設(shè)置的:

list-max-ziplist-size -2

參數(shù)可選值從-1到-5,其含義如下:

1) -5:每個quicklist節(jié)點上的ziplist大小不能超過64kb。

2) -4:每個quicklsit節(jié)點上的ziplist大小不能超過32kb。

3) -3:每個quicklsit節(jié)點上的ziplist大小不能超過16kb。

4) -2:每個quicklsit節(jié)點上的ziplist大小不能超過8kb。

5) -1:每個quicklsit節(jié)點上的ziplist大小不能超過4kb。

畫外音:在Redis 3.2 之后,我們也可以通過命令來驗證:

192.168.80.100:6379> rpush testkey "edison" "andy" "leo" 3 192.168.80.100:6379> object encoding testkey quicklist 192.168.80.100:6379> rpush testkey "wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww" 4 192.168.80.100:6379> object encoding testkey quicklist

綜述,快速列表的本質(zhì)其實是對壓縮列表的一次封裝,使用小塊的壓縮列表來組織,既可以保證內(nèi)存占用較小,也可以保證操作性能

End總結(jié)

本文總結(jié)了Redis的List類型在何時使用壓縮列表,何時使用雙向鏈表,以及快速列表的基本概念。當(dāng)然,更多的內(nèi)容還是需要自行去搜索學(xué)習(xí),意猶未盡的童鞋也可以去分析源碼。最后,如果你對其他集合類型也有此類問題,你可以參考下面附錄中的內(nèi)容,而至于Why,則可以自行百度搜索了解。

Anyway,對于Redis集合類型的底層思想采用了兩種數(shù)據(jù)結(jié)構(gòu)的設(shè)計思想是值得我們學(xué)習(xí)借鑒的,它其實充分體現(xiàn)了軟件設(shè)計中的Tradeoff(權(quán)衡)思想。對于Redis來說,即在主體目標(biāo)是保證性能的大約束前提下,權(quán)衡多方因素如操作時間和空間占用,以達(dá)到較為穩(wěn)定的運行表現(xiàn)。對于軟件設(shè)計來說,也需要在時間 vs 空間,新技術(shù) vs 老技術(shù),優(yōu)雅 vs 效率,輕度設(shè)計 vs 重度設(shè)計等之間做權(quán)衡,一個問題總會有多種解決方案可以實現(xiàn),在特定的時間段,永遠(yuǎn)沒有最完美的設(shè)計,只有較合適的設(shè)計。在實際中,它可能結(jié)合了多種因素的考慮,不斷地去粗取精,迭代為更好的設(shè)計。

Ref附錄

Hash:

Set:

Sorted Set(zset):

參考資料

極客時間,蔣德鈞《Redis核心技術(shù)與實戰(zhàn)》

年終總結(jié):Edison的2020年終總結(jié)

數(shù)字化轉(zhuǎn)型:我在傳統(tǒng)企業(yè)做數(shù)字化轉(zhuǎn)型

C#刷題:C#刷劍指Offer算法題系列文章目錄

.NET面試:.NET開發(fā)面試知識體系

.NET大會:2020年中國.NET開發(fā)者大會PDF資料

??

?

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的《Redis核心技术与实战》学习总结(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。