成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Redis 哈希結(jié)構(gòu)內(nèi)存模型剖析

Salamander / 3122人閱讀

摘要:本文共字,閱讀大約需要分鐘概述在前文字符串類型內(nèi)部編碼剖析之中已經(jīng)剖析過(guò)最基本的類型的內(nèi)部是怎么編碼和存儲(chǔ)的,本文再來(lái)闡述中使用最為頻繁的數(shù)據(jù)類型哈?;蚍Q散列,在內(nèi)部是怎么存的。

本文共 1231字,閱讀大約需要 5分鐘 !

概述

在前文《Redis字符串類型內(nèi)部編碼剖析》之中已經(jīng)剖析過(guò) Redis最基本的 String類型的內(nèi)部是怎么編碼和存儲(chǔ)的,本文再來(lái)闡述 Redis中使用 最為頻繁的數(shù)據(jù)類型:哈希(或稱散列),在Redis內(nèi)部是怎么存的。

實(shí)驗(yàn)源碼環(huán)境:Redis 4.0.10

注: 本文首發(fā)于  My Personal Blog,歡迎光臨 小站

本文內(nèi)容腦圖如下:


哈希類型內(nèi)部編碼詳情

對(duì)于 Redis的常用 5 種數(shù)據(jù)類型(String、Hash、List、Set、sorted set),每種數(shù)據(jù)類型都提供了 最少兩種 內(nèi)部的編碼格式,而且每個(gè)數(shù)據(jù)類型內(nèi)部編碼方式的選擇 對(duì)用戶是完全透明的,Redis會(huì)根據(jù)數(shù)據(jù)量自適應(yīng)地選擇較優(yōu)化的內(nèi)部編碼格式。

如果想查看某個(gè)鍵的內(nèi)部編碼格式,可以使用 OBJECT ENCODING keyname 指令來(lái)進(jìn)行,比如:

127.0.0.1:6379> 
127.0.0.1:6379> set foo bar
OK
127.0.0.1:6379> 
127.0.0.1:6379> object encoding foo  // 查看某個(gè)Redis鍵值的編碼
"embstr"
127.0.0.1:6379> 
127.0.0.1:6379> 

對(duì)于使用最為頻繁的 Hash類型,其內(nèi)部編碼方式可能有兩種:

OBJ_ENCODING_ZIPLIST(壓縮列表)

OBJ_ENCODING_HT(哈希表)

Redis 會(huì)根據(jù)數(shù)據(jù)量的情況來(lái)自適應(yīng)地選擇這兩種編碼方式中 較優(yōu) 的一種,而這一切對(duì)用戶完全透明。

數(shù)據(jù)條目較少,數(shù)據(jù)值較小 的時(shí)候 Redis會(huì)采用 壓縮列表(OBJ_ENCODING_ZIPLIST)編碼方式進(jìn)行存儲(chǔ)。這里成員"較少",成員值"較小"的標(biāo)準(zhǔn)可以通過(guò)如下配置項(xiàng)進(jìn)行配置:

hash-max-ziplist-entries 512
hash-max-ziplist-value 64

Redis 默認(rèn)給出了默認(rèn)值,當(dāng)然用戶可根據(jù)實(shí)際情況自行配置。

當(dāng) Hash類型鍵的字段個(gè)數(shù) < hash-max-ziplist-entries 并且 每個(gè)字段名和字段值的長(zhǎng)度 < hash-max-ziplist-value 時(shí),Redis 會(huì)使用 OBJ_ENCODING_ZIPLIST來(lái)存儲(chǔ)該鍵,反之則會(huì)轉(zhuǎn)換為 OBJ_ENCODING_HT的編碼方式。

口說(shuō)無(wú)憑,我們不妨先來(lái)做個(gè)實(shí)驗(yàn)感受一下吧:

很明顯該實(shí)驗(yàn)驗(yàn)證了當(dāng) 字段值長(zhǎng)度大于64時(shí),編碼格式會(huì)由 ZIPLIST方式切換為 Hashtable方式。

源碼之前,了無(wú)秘密,我們?cè)賮?lái)看一下Redis關(guān)于這部分切換的源碼實(shí)現(xiàn),那就理解得更加清楚了:

下面詳解 OBJ_ENCODING_ZIPLISTOBJ_ENCODING_HT 這兩種編碼格式的內(nèi)部存儲(chǔ)模型,知道了其各自特點(diǎn)和優(yōu)缺點(diǎn),自然也就明白了Redis內(nèi)部使用它們的意圖。


OBJ_ENCODING_ZIPLIST 編碼

Ziplist 壓縮列表是一種緊湊編碼格式,總體思想是時(shí)間換空間,即以部分讀寫(xiě)性能為代價(jià),來(lái)?yè)Q取極高的內(nèi)存空間利用率,因此只會(huì)用于 字段個(gè)數(shù)少,且字段值也較小 的場(chǎng)景。

壓縮列表內(nèi)存利用率極高的原因與其連續(xù)內(nèi)存的特性是分不開(kāi)的,其典型的內(nèi)存結(jié)構(gòu)可以用下圖形象地展示出來(lái):

所以如果用 Ziplist來(lái)存儲(chǔ) Redis的散列類型的話,元素的排列方式就變成了如下圖所示的形象示意圖:即key和value都是邏輯連續(xù)內(nèi)存:


OBJ_ENCODING_HT 編碼

OBJ_ENCODING_HT 這種編碼方式內(nèi)部才是真正的哈希表結(jié)構(gòu),或稱為字典結(jié)構(gòu),其可以實(shí)現(xiàn)O(1)復(fù)雜度的讀寫(xiě)操作,因此效率很高。

在 Redis內(nèi)部,從 OBJ_ENCODING_HT類型到底層真正的散列表數(shù)據(jù)結(jié)構(gòu)是一層層嵌套下去的,關(guān)系如下:

這一關(guān)系我們可以從 Redis哈希表定義部分的源碼來(lái)看出:

下面來(lái)詳解一下各個(gè)部分:

關(guān)于哈希節(jié)點(diǎn)(dictEntry)

關(guān)于哈希表(dictht)和字典(dict)

關(guān)于dictType

Redis如何計(jì)算Hash值

Redis計(jì)算Hash的源代碼如下:

這是一個(gè) C語(yǔ)言宏定義,其實(shí)幕后真正承擔(dān) Hash值計(jì)算的是上面介紹的 dictType結(jié)構(gòu)體中的函數(shù)指針 hashFunction。

而該 hashFunction函數(shù)指針在初始化時(shí)會(huì)對(duì)應(yīng)被賦值為一個(gè)個(gè)真實(shí)的計(jì)算 Hash值的實(shí)際函數(shù),就像下面這樣:

Redis如何計(jì)算存取索引Index值

Index值的計(jì)算依賴于上面計(jì)算得出的 Hash值,代碼如下:

到此,還有一個(gè)一直非常值得關(guān)注的細(xì)節(jié):即字典 dict里總是保存有兩個(gè) Hash表結(jié)構(gòu) ht[2],以及與其高度相關(guān)的 rehash操作,這在下一篇文章里詳解。

后 記
由于能力有限,若有錯(cuò)誤或者不當(dāng)之處,還請(qǐng)大家批評(píng)指正,一起學(xué)習(xí)交流!

My Personal Blog

我的半年技術(shù)博客之路



文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/17777.html

相關(guān)文章

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<