1. 物件的型別與編碼
Redis中的每個物件都由一個redisObject結構表示,該結構中和保存資料有關的三個屬性分別是type屬性,encoding屬性和ptr屬性:
1.1 型別
對于redis中保存的鍵值對來說,鍵總是一個字串物件,而值則可以是字串物件、串列物件、哈希物件、集合物件或者有序集合物件中的一種,

字串鍵指,鍵所對應的值為字串物件;串列鍵指鍵所對應的值為串列物件
1.2 編碼與底層實作
物件的ptr指標指向物件的底層實作資料結構,而這些資料結構由物件的encoding屬性決定,

每種型別的物件使用了至少兩種不同的編碼,
Redis可以根據不同的使用場景來為一個物件設定不同的編碼,從而優化物件在某一場景下的效率,
在串列物件包含元素較少時,Redis使用壓縮串列作為串列物件的底層實作,
- 壓縮串列比雙端串列更節約記憶體,并且在元素較少時,記憶體以連續會方式保存的壓縮串列比起雙端鏈表可以更快的被載入到記憶體中
- 隨著串列物件包含的元素越來越多,物件會將底層實作從壓縮串列轉向功能更強、也更適合保存大量元素的雙端鏈表上面
2. 字串物件
字串物件的編碼可以是int、raw(字串值得長度大于39位元組)或者embstr(字串長度小于39位元組),使用embstr編碼的字串物件來保存短字串值有以下好處:
- embstr編碼將創建的字串所需要的記憶體分配次數從raw編碼的兩次降為一次
- 釋放embstr編碼的字串物件只需要一次記憶體釋放函式
- embstr編碼的字串物件的所有資料都保存在一塊連續的記憶體里,使用快取讀取更快

2.1 編碼的轉換
字串物件的編碼從int變為raw,
embstr編碼的字串是只讀的,embstr編碼的字串物件在執行修改命令后,總會變成一個raw編碼的字串物件,

2.2 字串命令的實作

3. 串列物件
串列物件的編碼是ziplist或者linkedlist,
3.1 編碼轉換
同時滿足以下兩個條件時,串列物件用ziplist編碼:
- 串列物件保存的所有字串元素的長度小于64位元組
- 串列物件保存的元素數量小于512個
3.2 串列命令的實作
4. 哈希物件
哈希物件的編碼可以是ziplist或者hashtable,

4.1 編碼轉換
當哈希物件同時滿足以下兩個條件時,哈希物件使用ziplist編碼:
- 哈希物件保存的所有鍵值對的鍵和值的字串長度小于64位元組
- 哈希物件保存的鍵值對數量小于512個
4.2 哈希命令的實作
5. 集合物件
集合物件的編碼可以是intset或者hashtable,
5.1 編碼的轉換
集合物件需要同時滿足以下兩個條件,物件使用intset編碼:
- 集合物件保存的所有元素都是整數值
- 集合物件保存的數量不超過512個
5.2 集合命令的實作
6. 有序集合物件
有序集合物件的編碼是ziplist后者skiplist,
有序集合元素會同時被保存在字典和跳躍表中,
如果只使用字典來實作有序集合,那么雖然能以O(1)復雜度查找成員分值,但是,因為字典以無序方式來保存集合元素,所以每次執行ZRANK、ZRANGE等命令時,程式都需要對字典保存的所有元素進行排序,需要至少O(NlogN)時間復雜度,以及額外O(N)的記憶體空間,使用跳躍表可以排位的時間復雜度為O(logN),但如果沒有字典,查找成員分值的復雜度會升高到O(logN),為了讓有序集合的查找和范圍型操作盡可能快的執行,有序集合同時使用字典和跳躍表兩種資料結構,

6.1 編碼的轉化
有序集合同時滿足兩個條件時,物件使用ziplist編碼:
- 有序集合元素數小于128個
- 有序集合保存的所有元素成員的長度都小于64位元組
6.2 有序集合命令的實作
7. 型別檢查與命令多型
有些命令可以對任何型別的鍵執行,比如DEL命令,EXPIRE命令,RENAME命令,TYPE命令,OBJECT命令等,
而另一些命令只能對特定型別的鍵執行:

7.1 型別檢查的實作
型別特定命令所進行的型別檢查是通過Redisobject結構的type屬性來實作的:

7.2 多型命令的實作

8. 記憶體回收
C語言不具備記憶體回識訓制,Redis使用參考計數(reference counting)來實作記憶體回識訓制,
物件的參考計數資訊會隨著物件的使用狀態而不斷變化:
- 在創建一個新物件時,參考計數的值會被初始化為1
- 當物件被一個新程式使用時,參考計數值增1
- 當物件不再被一個程式使用時,它的參考計數值會減一
- 當物件的參考計數變為0時,物件所占用的記憶體會被釋放
9. 物件共享
在Redis中,多個鍵共享同一個值物件需要以下兩個步驟:
1) 將資料庫鍵的值指標指向一個現有的值物件
2) 將被共享的值物件的參考計數增一
目前,Redis會在初始化服務器時,創建0到9999的所有整數值物件,當服務器需要用到值0到9999的字串物件時,服務器會使用這些共享物件,
10. 物件的空轉時長
lru屬性記錄了物件最后一次被命令程式訪問的時間,
如果服務器啟用了maxmemory選項,并且服務器用于回收記憶體的演算法為volatile-lru或者allkeys-lru,如果服務器占用的記憶體超過了maxmemory選項所設定的上限值,空轉時長較高的鍵會優先被服務器釋放,從而回收記憶體,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296140.html
標籤:其他
上一篇:第一章 資料結構
下一篇:第三章 資料庫
