前面我們看了Redis用到的主要資料結構,如簡單動態字串(SDS)、雙向連結串列、字典、壓縮列表、整數集合等。

但是Redis並沒有直接使用這些資料結構來實現鍵值對,而是基於這些資料結構建立了一個物件系統,這個系統包括字串物件、列表物件、雜湊物件、集合物件、有序集合物件,除此之外,redis的物件系統還實現了基於計數技術的記憶體回收機制,另外redis還通過引用計數技術實現了物件共享機制(適當條件下,多個數據庫鍵共享同一個物件來節約記憶體)。

最後,redis的物件帶有訪問時間記錄資訊,該資訊可以用於計算資料庫鍵的空轉時長,在伺服器啟用了maxmemory功能的情況下,空轉時長較大的鍵會優先被伺服器刪除。

 

1、Redis中的每個結構都是由redisObject結構標識,包含ptr(指向底層實現的資料結構)、encoding(決定用那種底層資料結構)、type等屬性。

 

2、當我們建立一個鍵值對時,我們至少會建立兩個物件:鍵物件(字串物件),值物件(物種型別)。

 

3、字串物件的編碼可以是整數、raw或者enbstr、sds

  1. enbstr(短字串長度小於32)呼叫一次分配記憶體函式,分配一個連續的記憶體包含redisObject結構與sdshdr結構,不包含修改命令,執行任何修改命令會轉為raw物件。

  2. sds(字串長度超過32)。

  3. raw 會呼叫兩次記憶體分配分別建立redisObject結構與sdshdr結構。

 

4、列表物件,列表物件的編碼可以是ziplist或者linkedlist

  1. ziplist使用壓縮列表作為底層實現。列表物件儲存的所有字串元素長度都小於64位元組,元素數量小於512個時使用壓縮列表做為底層實現。

  2. linkedlist編碼列表物件使用雙向連結串列作為底層實現,每個雙向連結串列節點都儲存一個字串物件。

 

5、雜湊物件

  1. 雜湊物件的編碼可以是ziplist或者hashtable

  2. ziplist編碼的雜湊物件使用壓縮表作為底層實現,當由新的鍵值對加入到hash物件時,程式會先將儲存了鍵的壓縮列表節點推入到壓縮列表的表尾,然後將儲存了值的壓縮列表節點推入到壓縮列表的表尾。

  3. 使用hashtable作為編碼的雜湊物件使用字典作為底層實現,鍵使用字串物件,值使用字串物件。

6、集合物件

  1. 集合物件的編碼可以是 intset或者是hashtable

  2. intset編碼的集合物件使用整數集合作為底層實現。

  3. hashtable編碼的集合物件使用字典作為底層實現,字典的每個鍵都是一個字串物件,每個字串物件包含一個集合元素,而欄位的值則全部設定為null。

     

     

  4. 物件轉換 。intset轉hashtable條件:元素中不全是整數或者元素數量超過512.

 

7、有序集合物件

  1. 有序集合的編碼可以是ziplist 或者skiplist

  2. ziplist編碼的壓縮列表物件使用壓縮列表作為底層實現,每個集合元素使用兩個挨在一起的壓縮列表節點來儲存,第一個節點儲存元素的成員(member)第二個元素則儲存元素的分值(score)。

  3. skiplist編碼的有序集合物件使用zset結構作為底層實現,一個zset結構同時包含一個字典和一個跳躍表。

  4. typedef struct zset{
        zskiplist *zsl;
        dict *dict;//儲存從成員到分值的對映,鍵儲存元素成員 值儲存了分數。
    }

     

  5. 解釋下為什麼同時使用字典與跳躍表來實現有序集合:雖然用兩種結構的任意一種都能實現有序集合,但是當我們只是用字典來實現有序集合時,由於字典是一個無序的儲存元素,當我們實行範圍操作時,需要先對所有的元素進行排序,這裡所使用的時間複雜度至少為O(NlogN),並且有額外的記憶體消費;另外如果只使用跳躍表來實現有序集合時,雖然範圍操作的優勢被保留,但是沒有了字典根據成員查詢分值時這一操作的複雜度將從O(1)提升到O(logN)。

  6. 編碼轉換,當元素的數量小於128,且每個元素的長度都小於64位元組時,使用ziplist。

8、記憶體回收

  1. 每個物件的引用技術資訊由redisObject結構的refcount屬性記錄。

  2. 建立物件時,計數值會被預設初始化為1,被程式使用時,計數器加一,不再被使用時,計數器減一,當計數器為0時,物件佔用的記憶體會被釋放。

 

9、物件空轉時長

  1. 物件空轉時長使用redisObjet結構中的lru屬性記錄,該屬性記錄物件最後一次被訪問的時間。

 

--------- end --------

 

每天學一點,總會有收穫。

 

說明:尊重作者智慧財產權,文中內容參考《Redis設計與實現》,僅在此做學習與大家分享。

 

&n