redis object 對象系統

redis object對象系統

概述

redis 當中, sds字符串, adlist雙向鏈表, dict字典, ziplist壓縮鏈表, intset整數集合等均爲底層數據結構redis

redis 並無使用這些基本數據結構來實現數據庫應用, 而是基於這些底層數據結構之上, 構建了一個對象系統, 全部的操做都是基於對象來進行操做算法

對象結構說明 (src/redis.h)

  • 對象結構數據庫

    • // redis 對象結構
      typedef struct redisObject {
          // 類型
          unsigned type:4;
          // 編碼
          unsigned encoding:4;
          // 對象最後一次被訪問的時間
          unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */
          // 引用計數
          int refcount;
          // 指向實際值的指針
          void *ptr;
      } robj;
  • 對象類型api

    • // 對象類型
      // 字符串
      #define REDIS_STRING 0
      // 鏈表
      #define REDIS_LIST 1
      // 集合
      #define REDIS_SET 2
      // 有序集合
      #define REDIS_ZSET 3
      // 哈希
      #define REDIS_HASH 4
  • 對象編碼安全

    • // 對象編碼
      // 普通的 sds 結構
      #define REDIS_ENCODING_RAW 0     /* Raw representation */
      // 整型
      #define REDIS_ENCODING_INT 1     /* Encoded as integer */
      // 哈希
      #define REDIS_ENCODING_HT 2      /* Encoded as hash table */
      // 壓縮圖, 沒看到有應用
      #define REDIS_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
      // 普通鏈表
      #define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
      // 壓縮鏈表
      #define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
      // 整數集合
      #define REDIS_ENCODING_INTSET 6  /* Encoded as intset */
      // 跳躍表
      #define REDIS_ENCODING_SKIPLIST 7  /* Encoded as skiplist */
      // emb 編碼的字符串
      #define REDIS_ENCODING_EMBSTR 8  /* Embedded sds string encoding */
  • 引用計數服務器

  • 總結數據結構

    redis 的對象系統總共有 5 種類型, 可是在使用上每種類型根據不一樣的使用場景會採用不一樣的編碼, 不一樣的對象編碼會使用不一樣的底層存儲結構, 這樣作是爲了性能考慮, 因爲數據量的不一樣, 使用不一樣的結構對效率的影響不一樣dom

    對象類型函數

    名稱 類型
    REDIS_STRING 字符串
    REDIS_LIST 列表
    REDIS_SET 集合
    REDIS_ZSET 有序集合
    REDIS_HASH 哈希

    對象編碼性能

    名稱 編碼
    REDIS_ENCODING_RAW 普通 sds 字符串
    REDIS_ENCODING_INT 整數
    REDIS_ENCODING_EMBSTR emb 編碼的字符串
    REDIS_ENCODING_LINKEDLIST 普通鏈表
    REDIS_ENCODING_ZIPLIST 壓縮鏈表
    REDIS_ENCODING_HT 哈希
    REDIS_ENCODING_SKIPLIST 跳躍表
    REDIS_ENCODING_INTSET 整數集合
    REDIS_ENCODING_ZIPMAP 壓縮圖

    對象類型與編碼之間的關係

    類型 編碼 對象
    REDIS_STRING REDIS_ENCODING_RAW 普通 sds 字符串
    REDIS_STRING REDIS_ENCODING_INT 整數字符串
    REDIS_STRING REDIS_ENCODING_EMBSTR emb 編碼字符串
    REDIS_LIST REDIS_ENCODING_LINKEDLIST 普通雙向鏈表
    REDIS_LIST REDIS_ENCODING_ZIPLIST 壓縮鏈表實現的鏈表結構
    REDIS_SET REDIS_ENCODING_HT 哈希結構實現的集合
    REDIS_SET REDIS_ENCODING_INTSET 整數集合實現的結合
    REDIS_ZSET REDIS_ENCODING_SKIPLIST 跳躍表實現的有序集合
    REDIS_ZSET REDIS_ENCODING_ZIPLIST 壓縮鏈表實現的有序集合
    REDIS_HASH REDIS_ENCODING_HT 哈希表實現的哈希
    REDIS_HASH REDIS_ENCODING_ZIPLIST 壓縮鏈表實現的哈希

各個對象的特性

字符串對象

  • long long 整型在 redis 中是使用字符串存儲的

    • // 根據傳入的 long long 整數, 建立字符串對象
      robj *createStringObjectFromLongLong(long long value) {
          robj *o;
          /*
          * value 大小符合 REDIS_SHARED_INTEGERS 共享整數範圍
          * 返回一個共享對象
          */
          if (value >= 0 && value < REDIS_SHARED_INTEGERS) {
              incrRefCount(shared.integers[value]);
              o = shared.integers[value];
          } else {
              // 不符合共享範圍,建立一個新的整數對象
              if (value >= LONG_MIN && value <= LONG_MAX) {
                  // 設置相應的 robj 的值
                  o = createObject(REDIS_STRING, NULL);
                  o->encoding = REDIS_ENCODING_INT;
                  o->ptr = (void*)((long)value);
              // 值不能用 long 類型保存(long long 類型),將值轉換爲字符串,
              // 並建立一個 REDIS_ENCODING_RAW 的字符串對象來保存值
              } else {
                  o = createObject(REDIS_STRING,sdsfromlonglong(value));
              }
          }
      
          return o;
      }
      • 對於整數, redis 有一個共享整數的概念, 用於將一些經常使用範圍的整數在 redis 啓動時就建立成對象, 後續全部落在這個範圍內的整數, 均使用這個共享對象, 節省了大量整數的對象建立過程

      • 共享整數範圍閾值爲 10000

        • #define REDIS_SHARED_INTEGERS 10000
      • 整數的編碼類型不必定都是 REDIS_ENCODING_INT, 當整數值超過了 long 的範圍時, 存儲的編碼類型會變爲 REDIS_ENCODING_RAW

  • long double 浮點型在 redis 中也是使用字符串存儲的

    • // 將 long double 浮點型存儲爲字符串
      robj *createStringObjectFromLongDouble(long double value) {
          char buf[256];
          int len;
          // 使用 17 位小數精度,這種精度能夠在大部分機器上被 rounding 而不改變
          len = snprintf(buf,sizeof(buf),"%.17Lf", value);
          // 移除尾部的 0 
          if (strchr(buf,'.') != NULL) {
              char *p = buf+len-1;
              while(*p == '0') {
                  p--;
                  len--;
              }
              // 若是不須要小數點,那麼移除它
              if (*p == '.') len--;
          }
          // 建立對象
          return createStringObject(buf,len);
      }
  • 字符串須要 2 個結構體, robj 和 sdshdr, robj 用來封裝成 redis object, sdshdr 用來存儲真正的字符串內容

  • 建立 emb 編碼與 raw 編碼的字符串有一個閾值 REDIS_ENCODING_EMBSTR_SIZE_LIMIT, 當超過這個閾值, 當小於等於這個閾值時, 以 emb 編碼; 不然以 raw 編碼, REDIS_ENCODING_EMBSTR_SIZE_LIMIT 值爲 39

    • #define REDIS_ENCODING_EMBSTR_SIZE_LIMIT 39
      // 建立字符串對象
      robj *createStringObject(char *ptr, size_t len) {
          // 當小於等於 REDIS_ENCODING_EMBSTR_SIZE_LIMIT時, 以 emb 編碼
          if (len <= REDIS_ENCODING_EMBSTR_SIZE_LIMIT)
              return createEmbeddedStringObject(ptr,len);
          else
              // 不然以 raw 編碼
              return createRawStringObject(ptr,len);
      }
  • 建立 emb 編碼的字符串僅須要 1 次內存分配, raw 編碼的字符串須要 2 次內存分配, 相應的釋放內存時也是如此

  • emb 編碼的字符串 robj, sdshdr 內存是連續的, 而 raw 編碼的字符串內存是分開的, emb 編碼的字符串性能更好

  • 建立 emb 編碼字符串

    • // 建立 emb 編碼的字符串
      robj *createEmbeddedStringObject(char *ptr, size_t len) {
          // 分配 robj, sdshdr 內存
          robj *o = zmalloc(sizeof(robj)+sizeof(struct sdshdr)+len+1);
          struct sdshdr *sh = (void*)(o+1);
          // 設置 robj 的值
          o->type = REDIS_STRING;
          o->encoding = REDIS_ENCODING_EMBSTR;
          o->ptr = sh+1;
          o->refcount = 1;
          o->lru = LRU_CLOCK();
          // 設置 sdshdr 的值
          sh->len = len;
          sh->free = 0;
          if (ptr) {
              memcpy(sh->buf,ptr,len);
              sh->buf[len] = '\0';
          } else {
              memset(sh->buf,0,len+1);
          }
          return o;
      }
  • 建立 raw 編碼字符串

    • // 建立 raw 編碼字符串
      robj *createRawStringObject(char *ptr, size_t len) {
          // sdsnewlen 函數分配了 sdshdr 的內存
          return createObject(REDIS_STRING,sdsnewlen(ptr,len));
      }
    • robj *createObject(int type, void *ptr) {
          //  分配 robj 的內存
          robj *o = zmalloc(sizeof(*o));
          // 設置 robj 的值
          o->type = type;
          o->encoding = REDIS_ENCODING_RAW;
          o->ptr = ptr;
          o->refcount = 1;
          o->lru = LRU_CLOCK();
          return o;
      }
  • 字符串比較根據不一樣的 flag 使用不一樣的比較方法

    • flags

      // 二進制安全的方式, 調用 memcmp 函數
      #define REDIS_COMPARE_BINARY (1<<0)
      // 根據 ascii 碼比較, 調用 strcoll 函數
      #define REDIS_COMPARE_COLL (1<<1)

鏈表對象

  • 對象嵌套

    • redis object 裏有個對象嵌套的概念, 就是底層存儲的數據, 例如字符串, 實際上也是以字符串對象 sdshdr 存在的
  • redis 鏈表對象的編碼分爲 linkedlist (雙端鏈表), ziplist (壓縮鏈表)

  • redis 鏈表對象的編碼轉換

    • 當節點的長度大於 64 字節, 轉換爲雙端鏈表

      void listTypeTryConversion(robj *subject, robj *value) {
      
          // 確保 subject 爲 ZIPLIST 編碼
          if (subject->encoding != REDIS_ENCODING_ZIPLIST) return;
      
          if (sdsEncodedObject(value) &&
              // 看字符串是否過長
              sdslen(value->ptr) > server.list_max_ziplist_value)
                  // 將編碼轉換爲雙端鏈表
                  listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);
      }
    • 當鏈表存儲的節點數量大於等於 512 個, 轉換爲雙端鏈表

      void listTypePush(robj *subject, robj *value, int where) {
          // 是否須要轉換編碼?
          listTypeTryConversion(subject,value);
      
          if (subject->encoding == REDIS_ENCODING_ZIPLIST &&
              ziplistLen(subject->ptr) >= server.list_max_ziplist_entries)
                  listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);
      
          // 省略 ...
      }
    • server.list_max_ziplist_value 值在初始化服務器配置時設置爲 REDIS_LIST_MAX_ZIPLIST_VALUE

    • server.list_max_ziplist_entries 值在初始化服務器配置時設置爲 REDIS_LIST_MAX_ZIPLIST_ENTRIES

    • // 鏈表結構從 ziplist 編碼轉換爲 linkedlist 編碼的閾值
      // 最大節點數量閾值
      #define REDIS_LIST_MAX_ZIPLIST_ENTRIES 512
      // 最大字符串長度閾值
      #define REDIS_LIST_MAX_ZIPLIST_VALUE 64
      
      void initServerConfig() {
          // 省略
      
          server.list_max_ziplist_entries = REDIS_LIST_MAX_ZIPLIST_ENTRIES;
          server.list_max_ziplist_value = REDIS_LIST_MAX_ZIPLIST_VALUE;
      
          // 省略 ...
      }

集合對象

  • redis 集合的編碼轉換

    集合的 intset 編碼存儲的均爲整數

    • 集合的操做 api 在存入 intset 編碼時, 均會調用 isObjectRepresentableAsLongLong 函數, 來判斷是不是整數

    集合保存的元素數量不能超過 512 (REDIS_SET_MAX_INTSET_ENTRIES)

    int setTypeAdd(robj *subject, robj *value) {
        // 省略 ...
        
        // 添加成功
        // 檢查集合在添加新元素以後是否須要轉換爲字典
        if (intsetLen(subject->ptr) > server.set_max_intset_entries)
            setTypeConvert(subject,REDIS_ENCODING_HT);
    
        // 省略 ...
    }
    • server.set_max_intset_entries, 若集合的元素數量大於此值, 會將 intset 編碼轉換爲 ht 編碼

      • #define REDIS_SET_MAX_INTSET_ENTRIES 512
        
        void initServerConfig() {
            // 省略 ...
        
            server.set_max_intset_entries = REDIS_SET_MAX_INTSET_ENTRIES;
        
            // 省略 ...
        }

有序集合對象

  • 有序集合結構

    • // 有序集合
      typedef struct zset {
          // 字典, 鍵爲成員, 值爲分值
          dict *dict;
          // 跳躍表, 按分值排序成員
          zskiplist *zsl;
      } zset;
  • ​有序集合 ziplist 編碼與 skiplist 編碼之間的轉換

    • 當執行集合命令時, 判斷一些規則, 來決定是否使用 skiplist 編碼
      • 有序集合保存的元素數量大於 (128) server.zset_max_ziplist_entries

        • #define REDIS_ZSET_MAX_ZIPLIST_ENTRIES 128
      • 有序集合保存的元素大小大於 (64) server.zset_max_ziplist_value

        • #define REDIS_ZSET_MAX_ZIPLIST_VALUE 64
      • 命令距離

        • void zaddGenericCommand(redisClient *c, int incr) {
              // 省略 ...
          
              if (zzlLength(zobj->ptr) > server.zset_max_ziplist_entries)
                  zsetConvert(zobj,REDIS_ENCODING_SKIPLIST);
          
              if (sdslen(ele->ptr) > server.zset_max_ziplist_value)
                  zsetConvert(zobj,REDIS_ENCODING_SKIPLIST);
          
              // 省略 ...
          }

哈希對象

  • hash 的 ziplist 編碼將鍵和值分別存放在 ziplist 的 2 個節點, 鍵在前, 值在後

  • redis hash 的編碼轉換

    • 當知足如下 2 個條件時, redis hash 對象會使用 ziplist 編碼

      • 當 hash 的鍵值對數量小於 512 (server.hash_max_ziplist_entries)

        • #define REDIS_HASH_MAX_ZIPLIST_ENTRIES 512
          
          int hashTypeSet(robj *o, robj *field, robj *value) {
              // 省略 ...
          
              // 檢查在添加操做完成以後,是否須要將 ZIPLIST 編碼轉換成 HT 編碼
              if (hashTypeLength(o) > server.hash_max_ziplist_entries)
                  hashTypeConvert(o, REDIS_ENCODING_HT);
          
              // 省略 ...
          }
      • 當 hash 的全部鍵和值的字符串長度均小於 64 字節 (server.hash_max_ziplist_value)

        • #define REDIS_HASH_MAX_ZIPLIST_VALUE 64
          
          void hashTypeTryConversion(robj *o, robj **argv, int start, int end) {
              int i;
              // 若是對象不是 ziplist 編碼,那麼直接返回
              if (o->encoding != REDIS_ENCODING_ZIPLIST) return;
              // 檢查全部輸入對象,看它們的字符串值是否超過了指定長度
              for (i = start; i <= end; i++) {
                  if (sdsEncodedObject(argv[i]) &&
                      sdslen(argv[i]->ptr) > server.hash_max_ziplist_value)
                  {
                      // 將對象的編碼轉換成 REDIS_ENCODING_HT
                      hashTypeConvert(o, REDIS_ENCODING_HT);
                      break;
                  }
              }
          }

總結

類型檢查

命令多態

內存回收

對象共享

  • 不一樣鍵的值指針指向的是同一個值對象
  • 值對象的引用計數 +1

object api (src/object.c)

函數 做用 備註
createObject 建立 robj 對象 robj createObject(int type, void ptr)
createRawStringObject 建立 raw 編碼的字符串對象 robj createRawStringObject(char ptr, size_t len)
createEmbeddedStringObject 建立 emb 壓縮算法壓縮的字符串對象 robj createRawStringObject(char ptr, size_t len)
createStringObject 建立字符串對象, raw 或 emb 編碼 robj createStringObject(char ptr, size_t len)
createStringObjectFromLongLong 建立 int 編碼的字符串對象 robj *createStringObjectFromLongLong(long long value)
createStringObjectFromLongDouble 建立浮點數的字符串對象, raw 或 emb 編碼 robj *createStringObjectFromLongDouble(long double value)
dupStringObject 複製字符串對象 robj dupStringObject(robj o)
createListObject 建立 linkedlist 編碼的列表對象 robj *createListObject(void)
createZiplistObject 建立 ziplist 編碼的列表對象 robj *createZiplistObject(void)
createSetObject 建立 ht 編碼的集合對象 robj *createSetObject(void)
createIntsetObject 建立 intset 編碼的集合對象 robj *createIntsetObject(void)
createHashObject 建立 ziplist 編碼的哈希對象 robj *createHashObject(void)
createZsetObject 建立 skiplist 編碼的有序集合對象 robj *createZsetObject(void)
createZsetZiplistObject 建立 ziplist 編碼的有序集合對象 robj *createZsetZiplistObject(void)
freeStringObject 釋放 raw 編碼的字符串對象 void freeStringObject(robj *o)
freeListObject 釋放鏈表對象 void freeListObject(robj *o)
freeSetObject 釋放集合對象 void freeSetObject(robj *o)
freeZsetObject 釋放有序集合對象 void freeZsetObject(robj *o)
freeHashObject 釋放哈希對象 void freeHashObject(robj *o)
incrRefCount 爲對象的引用加 1 void incrRefCount(robj *o)
decrRefCount 爲對象的引用減 1 void decrRefCount(robj *o)
decrRefCountVoid 對象的引用減 1 void decrRefCountVoid(void *o)
resetRefCount 重置對象的 refcount 爲 0 robj resetRefCount(robj obj)
checkType 檢查對象 o 的類型是否符合 type, 並返回客戶端信息 int checkType(redisClient c, robj o, int type)
isObjectRepresentableAsLongLong 對象 o 是否能夠表示爲 long long 類型, 將轉換後的值存入到 llval int isObjectRepresentableAsLongLong(robj o, long long llval)
tryObjectEncoding 嘗試對字符串對象進行編碼, 以節約內存 robj tryObjectEncoding(robj o)
getDecodedObject 將傳入的 robj 對象解析爲字符串對象 robj getDecodedObject(robj o)
compareStringObjectsWithFlags 比較字符串大小, 根據傳入的 flag 使用不一樣的函數比較 int compareStringObjectsWithFlags(robj a, robj b, int flags)
compareStringObjects 以二進制安全方式比較字符串大小 int compareStringObjects(robj a, robj b)
collateStringObjects 以 strcoll 函數比較字符串大小 int collateStringObjects(robj a, robj b)
equalStringObjects 判斷兩個字符串是否相等 int equalStringObjects(robj a, robj b)
stringObjectLen 獲取字符串對象中字符串長度 size_t stringObjectLen(robj *o)
getDoubleFromObject 從字符串對象 o 中獲取 double 值, 存入 target int getDoubleFromObject(robj o, double target)
getDoubleFromObjectOrReply 從對象 o 中獲取 double 值, 存入 target; 若失敗返回給定信息 int getDoubleFromObjectOrReply(redisClient c, robj o, double target, const char msg)
getLongDoubleFromObject 從對象 o 中獲取 long double 值, 存入 target int getLongDoubleFromObject(robj o, long double target)
getLongDoubleFromObjectOrReply 從對象 o 中獲取 long double 值, 存入 target; 若失敗返回給定信息 int getLongDoubleFromObjectOrReply(redisClient c, robj o, long double target, const char msg)
getLongLongFromObject 從對象 o 中獲取 long long 值, 存入 target int getLongLongFromObject(robj o, long long target)
getLongLongFromObjectOrReply 從對象 o 中獲取 long long 值, 存入 target; 若失敗返回給定信息 int getLongLongFromObjectOrReply(redisClient c, robj o, long long target, const char msg)
getLongFromObjectOrReply 從對象 o 中獲取 long 值, 存入 target; 若失敗返回給定信息 int getLongFromObjectOrReply(redisClient c, robj o, long target, const char msg)
strEncoding 返回給定 encoding 編碼的字符串表示 char *strEncoding(int encoding)
estimateObjectIdleTime 計算給定對象的空閒時長 unsigned long long estimateObjectIdleTime(robj *o)
objectCommandLookup OBJECT 命令獲取指定 key 的值對象, 不修改 lru robj objectCommandLookup(redisClient c, robj *key)
objectCommandLookupOrReply OBJECT 命令獲取指定 key 的之對象, 不修改 lru; 若失敗返回給定信息 robj objectCommandLookupOrReply(redisClient c, robj key, robj reply)
objectCommand OBJECT 命令 void objectCommand(redisClient *c)

list api (src/t_list.c)

函數 做用 備註
listTypeTryConversion 根據插入的 value 值, 看是否須要將鏈表 subject 從 ziplist 轉爲 linkedlist void listTypeTryConversion(robj subject, robj value)
listTypePush 向鏈表 subject 頭部或尾部添加值 value void listTypePush(robj subject, robj value, int where)
listTypePop 從鏈表 subject 頭部或尾部彈出節點 robj listTypePop(robj subject, int where)
listTypeLength 獲取鏈表 subject 的長度 unsigned long listTypeLength(robj *subject)
listTypeInitIterator 初始化鏈表迭代器 listTypeIterator listTypeInitIterator(robj subject, long index, unsigned char direction)
listTypeReleaseIterator 釋放鏈表迭代器 li void listTypeReleaseIterator(listTypeIterator *li)
listTypeNext 獲取迭代器當前指向的節點, 將其存入 entry int listTypeNext(listTypeIterator li, listTypeEntry entry)
listTypeGet 返回 entry 結構保存的節點, 轉爲 robj 結構 robj listTypeGet(listTypeEntry entry)
listTypeInsert 將 value 插入 entry 所在鏈表節點的前面或後面 void listTypeInsert(listTypeEntry entry, robj value, int where)
listTypeEqual 判斷對象 o 與 entry 節點值是否相等 int listTypeEqual(listTypeEntry entry, robj o)
listTypeDelete 刪除 entry 節點 void listTypeDelete(listTypeEntry *entry)
listTypeConvert 將 subject 編碼轉換爲 linkedlist void listTypeConvert(robj *subject, int enc)

set api (src/t_set.c)

函數 做用 備註
setTypeCreate 根據 value 值建立集合 robj setTypeCreate(robj value)
setTypeAdd 將 value 值添加到 subject 集合中 int setTypeAdd(robj subject, robj value)
setTypeRemove 將 value 值從 setobj 集合中刪除 int setTypeRemove(robj setobj, robj value)
setTypeIsMember 判斷 value 值是否在集合 subject 中 int setTypeIsMember(robj subject, robj value)
setTypeInitIterator 建立指定 subject 集合的迭代器 setTypeIterator setTypeInitIterator(robj subject)
setTypeReleaseIterator 釋放集合迭代器 void setTypeReleaseIterator(setTypeIterator *si)
setTypeNext 獲取迭代器當前指向的節點, 存入 objele, 返回的對象沒有增長引用計數, 對 copy-on-write 友好 int setTypeNext(setTypeIterator *si, robj **objele, int64_t *llele)
setTypeNextObject 獲取迭代器當前指向的節點, 老是返回一個新增的, 或者是引用計數增長的對象, 對 copy-on-write 非友好 robj setTypeNextObject(setTypeIterator si)
setTypeRandomElement 從集合中隨機獲取一個元素, 若集合編碼是 intset, 存到 llele; 若編碼是 ht, 存到 objele int setTypeRandomElement(robj *setobj, robj **objele, int64_t *llele)
setTypeSize 獲取集合的元素數量 unsigned long setTypeSize(robj *subject)
setTypeConvert 將集合 setobj 的編碼轉換爲給定的 ht 編碼 void setTypeConvert(robj *setobj, int enc)
qsortCompareSetsByCardinality 計算集合 s1 與集合 s2 的元素數量之差 int qsortCompareSetsByCardinality(const void s1, const void s2)
qsortCompareSetsByRevCardinality 計算集合 s2 與集合 s1 的元素數量之差 int qsortCompareSetsByRevCardinality(const void s1, const void s2)

hash api (src/t_hash.c)

函數 做用 備註
hashTypeTryConversion 嘗試將 ziplist 編碼的 hash 對象轉換成 ht 編碼 void hashTypeTryConversion(robj *o, robj ** argv, int start, int end)
hashTypeTryObjectEncoding 嘗試將 ht 編碼的鍵值對字符串對象分別進行編碼, 以節省內存 void hashTypeTryObjectEncoding(robj *subject, robj o1, robj o2)
hashTypeGetFromZiplist 從 ziplist 編碼的 hash 中獲取指定 field 相對應的值 int hashTypeGetFromZiplist(robj o, robj field, unsigned char ** vstr, unsigned int vlen, long long vll)
hashTypeGetFromHashTable 從 ht 編碼的 hash 中獲取指定 field 相對應的值 int hashTypeGetFromZiplist(robj o, robj field, unsigned char **vstr, unsigned int vlen, long long vll)
hashTypeGetObject 從 hash 中獲取指定 field 的值, 返回 robj 對象 robj hashTypeGetObject(robj o, robj *field)
hashTypeExists 判斷 hash 中指定 filed 是否存在 int hashTypeExists(robj o, robj field)
hashTypeSet 將鍵值對添加到 hash 中, 若鍵已存在, 則使用新值替換舊值 int hashTypeSet(robj o, robj field, robj *value)
hashTypeDelete 從 hash 中刪除指定 field 的鍵值對 int hashTypeDelete(robj o, robj field)
hashTypeLength 返回 hash 中鍵值對數量 unsigned long hashTypeLength(robj *o)
hashTypeInitIterator 建立 hash 迭代器 hashTypeIterator hashTypeInitIterator(robj subject)
hashTypeReleaseIterator 釋放 hash 迭代器 void hashTypeReleaseIterator(hashTypeIterator *hi)
hashTypeNext 獲取迭代器下個節點, 存入迭代器 int hashTypeNext(hashTypeIterator *hi)
hashTypeCurrentFromZiplist 從 ziplist 編碼的 hash 中, 獲取迭代器當前指向的節點的 field 或 value 對象 void hashTypeCurrentFromZiplist(hashTypeIterator *hi, int what, unsigned char **vstr, unsigned int vlen, long long vll)
hashTypeCurrentFromHashTable 從 ht 編碼的 hash 中, 獲取迭代器當前指向的節點的 field 或 value 對象 void hashTypeCurrentFromHashTable(hashTypeIterator *hi, int what, robj **dst)
hashTypeCurrentObject 獲取迭代器當前節點的 field 或 value 對象 robj hashTypeCurrentObject(hashTypeIterator hi, int what)
hashTypeLookupWriteOrCreate 按 key 在數據庫中查找並返回相應 hash 對象, 若對象不存在, 建立新 hash 對象並返回 robj hashTypeLookupWriteOrCreate(redisClient c, robj *key)
hashTypeConvertZiplist 將 ziplist 編碼的 hash 對象轉換成 ht 編碼 void hashTypeConvertZiplist(robj *o, int enc)
hashTypeConvert 將 hash 對象 o 轉換成指定 enc 編碼, 目前僅支持將 ziplist 編碼轉換爲 ht 編碼 void hashTypeConvert(robj *o, int enc)
相關文章
相關標籤/搜索