深入理解:Redis雜湊結構記憶體模型剖析

來源:互聯網
上載者:User

標籤:記憶體   轉換   分布   初始化   讀寫   開發   標準   ddd   enc   

 

本文主要闡述 Redis中使用 最為頻繁的資料類型:雜湊(或稱散列),在Redis內部是怎麼存的。

本文內容腦圖如下:

 

雜湊類型內部編碼詳情

對於 Redis的常用 5 種資料類型(String、Hash、List、Set、sorted set),每種資料類型都提供了 最少兩種 內部的編碼格式,而且每個資料類型內部編碼方式的選擇 對使用者是完全透明的,Redis會根據資料量自適應地選擇較最佳化的內部編碼格式。

如果想查看某個鍵的內部編碼格式,可以使用 OBJECT ENCODING keyname 指令來進行,比如:

127.0.0.1:6379> 127.0.0.1:6379> set foo barOK127.0.0.1:6379> 127.0.0.1:6379> object encoding foo // 查看某個Redis索引值的編碼"embstr"127.0.0.1:6379> 127.0.0.1:6379> 

對於使用最為頻繁的 Hash類型,其內部編碼方式可能有兩種:

  • OBJ_ENCODING_ZIPLIST(壓縮列表)
  • OBJ_ENCODING_HT(雜湊表)

Redis 會根據資料量的情況來自適應地選擇這兩種編碼方式中 較優 的一種,而這一切對使用者完全透明。

在 資料條目較少,資料值較小 的時候 Redis會採用 壓縮列表(OBJ_ENCODING_ZIPLIST)編碼方式進行儲存。這裡成員"較少",成員值"較小"的標準可以通過如下配置項進行配置:

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

Redis 預設給出了預設值,當然使用者可根據實際情況自行配置。

當 Hash類型鍵的欄位個數 < hash-max-ziplist-entries 並且 每個欄位名和欄位值的長度 < hash-max-ziplist-value 時,Redis 會使用 OBJ_ENCODING_ZIPLIST來儲存該鍵,反之則會轉換為 OBJ_ENCODING_HT的編碼方式。

口說無憑,我們不妨先來做個實驗感受一下吧:

 

很明顯該實驗驗證了當 欄位值長度大於64時,編碼格式會由 ZIPLIST方式切換為 Hashtable方式。

源碼之前,了無秘密,我們再來看一下Redis關於這部分切換的源碼實現,那就理解得更加清楚了:

 

 

下面詳解 OBJ_ENCODING_ZIPLIST 和 OBJ_ENCODING_HT 這兩種編碼格式的內部儲存模型,知道了其各自特點和優缺點,自然也就明白了Redis內部使用它們的意圖。

OBJ_ENCODING_ZIPLIST 編碼

Ziplist 壓縮列表是一種緊湊編碼格式,總體思想是時間換空間,即以部分讀寫效能為代價,來換取極高的記憶體空間利用率,因此只會用於 欄位個數少,且欄位值也較小 的情境。

壓縮列表記憶體利用率極高的原因與其連續記憶體的特性是分不開的,其典型的記憶體結構可以用形象地展示出來:

 

所以如果用 Ziplist來儲存 Redis的散列類型的話,元素的相片順序就變成了如所示的形象:即key和value都是邏輯連續記憶體:

 

OBJ_ENCODING_HT 編碼

OBJ_ENCODING_HT 這種編碼方式內部才是真正的雜湊表結構,或稱為字典結構,其可以實現O(1)複雜度的讀寫操作,因此效率很高。

在 Redis內部,從 OBJ_ENCODING_HT類型到底層真正的散列表資料結構是一層層嵌套下去的,關係如下:

 

這一關係我們可以從 Redis雜湊表定義部分的源碼來看出:

 

下面來詳解一下各個部分:

  • 關於雜湊節點(dictEntry)

 

  • 關於雜湊表(dictht)和字典(dict)

 

  • 關於dictType

 

  • Redis如何計算Hash值

Redis計算Hash的原始碼如下:

 

這是一個 C語言宏定義,其實幕後真正承擔 Hash值計算的是上面介紹的 dictType結構體中的函數指標 hashFunction。

而該 hashFunction函數指標在初始化時會對應被賦值為一個個真實的計算 Hash值的實際函數,就像下面這樣:

 

  • Redis如何計算存取索引Index值

Index值的計算依賴於上面計算得出的 Hash值,代碼如下:

 

到此,還有一個一直非常值得關注的細節:即字典 dict裡總是儲存有兩個 Hash表結構 ht[2],以及與其高度相關的 rehash操作,這在下一篇文章裡詳解。

原文連結:https://my.oschina.net/hansonwang99/blog/1934354

由於能力有限,若有錯誤或者不當之處,還請大家批評指正,一起學習交流!

順便在此給大家推薦一個Java架構方面的交流學習群:698581634,裡面會分享一些資深架構師錄製的視頻資料:有Spring,MyBatis,Netty源碼分析,高並發、高效能、分布式、微服務架構的原理,JVM效能最佳化這些成為架構師必備的知識體系,主要針對Java開發人員提升自己,突破瓶頸,相信你來學習,會有提升和收穫。

深入理解:Redis雜湊結構記憶體模型剖析

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.