1. 程式人生 > 實用技巧 >Redis中的物件

Redis中的物件

Redis中的每個物件都由一個redisObject結構表示,該結構中和儲存資料有關的三個屬性分別是typeencodingptr

typedef struct redisObject {
    unsigned type:4; // 型別
    unsigned encoding:4;// 編碼
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
    int refcount;
    void *ptr;// 指向底層實現資料結構的指標
} robj;

1. 型別

Redis一共有5種類型,其中鍵值總是一個字串物件,而可以是5中型別中的任意一種。可以通過TYPE命令來檢視對應的的型別

# 鍵為字串物件,值為字串物件
redis> SET msg "hello world"
OK
redis> TYPE msg
string
# 鍵為字串物件,值為列表物件
redis> RPUSH numbers 1 3 5
(integer)6
redis> TYPE numbers
list
不同型別值物件的TYPE命令輸出
物件型別 物件type屬性值 TYPE命令的輸出
字串 REDIS_STRING
"string"
列表 REDIS_LIST "list"
雜湊 REDIS_HASH "hash"
集合 REDIS_SET "set"
有序集合 REDIS_ZSET "zset"

2. 編碼

物件的ptr指標指向物件的底層實現資料結構,而這些資料結構由物件的encoding屬性決定

redis> SET msg "hello world"
OK
redis> OBJECT ENCODING msg
"embstr" // msg為embstr型別
redis> SET story "long long long long long long long ago ..."
OK
redis> OBJECT ENCODING msg
"raw" // msg從embstr型別變成raw型別
redis> SADD numbers 1 3 5
(integer)3
redis> OBJECT ENCODING numbers
"intset" // numbers為intset型別
redis> SADD numbers "seven"
(integer)1
redis> OBJECT ENCODING numbers
"hashtable" // numbers從intset型別變成hashtable型別
不同型別和編碼的物件
型別 編碼常量 底層資料結構
REDIS_STRING REDIS_ENCODING_INT 整數
REDIS_STRING REDIS_ENCODING_IEMBSTR embstr編碼的簡單動態字串
REDIS_STRING REDIS_ENCODING_RAW 簡單動態字串
REDIS_LIST REDIS_ENCODING_ZIPLIST 壓縮列表
REDIS_LIST REDIS_ENCODING_LINKEDLIST 雙端連結串列
REDIS_HASH REDIS_ENCODING_ZIPLIST 壓縮列表
REDIS_HASH REDIS_ENCODING_HT 字典
REDIS_SET REDIS_ENCODING_INTSET 整數集合
REDIS_SET REDIS_ENCODING_HT 字典
REDIS_ZSET REDIS_ENCODING_ZIPLIST 壓縮列表
REDIS_ZSET REDIS_ENCODING_SKIPLIST 跳躍表
OBJECT ENCODING對不同型別編碼的輸出
編碼常量 OBJECT ENCODING命令輸出
REDIS_ENCODING_INT "int"
REDIS_ENCODING_IEMBSTR "embstr"
REDIS_ENCODING_RAW "raw"
REDIS_ENCODING_HT "hashtable"
REDIS_ENCODING_LINKEDLIST "linkedlist"
REDIS_ENCODING_ZIPLIST "ziplist"
REDIS_ENCODING_INTSET "intset"
REDIS_ENCODING_SKIPLIST "skiplist"

3. 物件底層資料結構

在Redis中為了節省空間,物件的編碼是會發生轉化,底層的資料結構也會隨著發生變化。

  • 字串物件編碼的轉換規則

    1. 如果一個字串物件儲存的是整數值,並且這個值可以用long型別來表示,那麼字串物件會將整數值儲存在物件結構ptr屬性裡面,並將字串物件的屬性設定為int
    2. 如果字串物件儲存的是一個字串值,並且長度小於39位元組,那麼字串物件將使用embstr編碼
    3. 對於 int編碼的字串物件來說,如果將值修改成字串,那麼字串物件的編碼將從int變為raw
    4. 對於 embstr編碼的字串物件來說,如果字串的長度大於39位元組,那麼字串物件的編碼將從embstr變為raw
  • 列表物件編碼的轉換規則

    1. 當列表物件儲存的所有字串元素的長度都小於64位元組,並且儲存的元素數量小於512個,物件將使用ziplist編碼
    2. 如果物件不滿足ziplist編碼的條件,物件將使用linkedlist編碼
  • 雜湊物件編碼的轉換規則

    1. 當雜湊物件儲存的所有鍵和值的字串長度都小於64位元組,並且鍵值對數量小於512個,物件將使用ziplist編碼
    2. 如果物件不滿足ziplist編碼的條件,物件將使用hashtable編碼
  • 集合物件編碼的轉換規則

    1. 當集合物件儲存的所有元素都是整數值,並且元素數量小於512個,物件將使用inset編碼
    2. 如果物件不滿足inset編碼的條件,物件將使用hashtable編碼
  • 有序集合物件編碼的轉換規則

    1. 當集合物件中儲存的元素數量小於128個,並且所有元素成員的長度都小於64位元組,物件將使用ziplist編碼
    2. 如果物件不滿足ziplist編碼的條件,物件將使用skiplist編碼

4. 物件型別檢查、回收、共享和空轉時長

  • 伺服器在執行某些命令之前,會先檢查給定鍵的型別能否執行指定的命令,而檢查一個鍵的型別就是檢查鍵的值物件的型別

  • Redis的物件帶有引用計數實現的記憶體回收機制,當一個物件不再被使用時,該物件鎖佔用的記憶體就會被自動釋放

  • Redis會自動共享值為0~9999的字串物件

  • 每個物件會記錄自己的最後一次被訪問的時間,這個時間可以用於計算物件的空轉時間。當回收演算法為volatile-lru或者allkeys-lru,那麼當伺服器佔用的記憶體超過了maxmemory選項所設定的上限時,空轉時間較高的那部分鍵會被伺服器優先釋放,從而回收記憶體