redis源码阅读之hash模型

2200阅读 0评论2019-04-13 stolennnxb
分类:NOSQL

redis当中哈希对象的底层存储使用的是ziplist和hashtable,其中个人觉得比较有意思的就是类型转换这一块了
首先,在redis当中(我读的是4.0.11)没有实现由hashtable转为ziplist的可能,具体见代码:

点击(此处)折叠或打开

  1. void hashTypeConvert(robj *o, int enc) {
  2.     if (o->encoding == OBJ_ENCODING_ZIPLIST) {
  3.         hashTypeConvertZiplist(o, enc);
  4.     } else if (o->encoding == OBJ_ENCODING_HT) {
  5.         serverPanic("Not implemented");
  6.     } else {
  7.         serverPanic("Unknown hash encoding");
  8.     }
  9. }
其次,发生转换的条件是:1)当前编码为ziplist;2)当前ziplist当中的entry个数大于512,或者ziplist当中最长的key/value占用字节大于64字节时。具体代码如下:

点击(此处)折叠或打开

  1. void hashTypeTryConversion(robj *o, robj **argv, int start, int end) {
  2.     int i;

  3.     if (o->encoding != OBJ_ENCODING_ZIPLIST) return;

  4.     for (i = start; i <= end; i++) {
  5.         if (sdsEncodedObject(argv[i]) &&
  6.             sdslen(argv[i]->ptr) > server.hash_max_ziplist_value)
  7.         {
  8.             hashTypeConvert(o, OBJ_ENCODING_HT);
  9.             break;
  10.         }
  11.     }
  12. }
其中的512和64是可以通过redis.conf中的两个配置项更改的,具体如下:

点击(此处)折叠或打开

  1. # Hashes are encoded using a memory efficient data structure when they have a
  2. # small number of entries, and the biggest entry does not exceed a given
  3. # threshold. These thresholds can be configured using the following directives.
  4. hash-max-ziplist-entries 512
  5. hash-max-ziplist-value 64
转化的流程就是遍历ziplist当中的key/value对,逐个插入到新建的hashtable当中,最后释放原有数据,将object当中的ptr指向新的hashtable,具体代码如下:

点击(此处)折叠或打开

  1. void hashTypeConvertZiplist(robj *o, int enc) {
  2.     serverAssert(o->encoding == OBJ_ENCODING_ZIPLIST);

  3.     if (enc == OBJ_ENCODING_ZIPLIST) {
  4.         /* Nothing to do... */

  5.     } else if (enc == OBJ_ENCODING_HT) {
  6.         hashTypeIterator *hi;
  7.         dict *dict;
  8.         int ret;

  9.         hi = hashTypeInitIterator(o);
  10.         dict = dictCreate(&hashDictType, NULL);

  11.         while (hashTypeNext(hi) != C_ERR) {
  12.             sds key, value;

  13.             key = hashTypeCurrentObjectNewSds(hi,OBJ_HASH_KEY);
  14.             value = hashTypeCurrentObjectNewSds(hi,OBJ_HASH_VALUE);
  15.             ret = dictAdd(dict, key, value);
  16.             if (ret != DICT_OK) {
  17.                 serverLogHexDump(LL_WARNING,"ziplist with dup elements dump",
  18.                     o->ptr,ziplistBlobLen(o->ptr));
  19.                 serverPanic("Ziplist corruption detected");
  20.             }
  21.         }
  22.         hashTypeReleaseIterator(hi);
  23.         zfree(o->ptr);
  24.         o->encoding = OBJ_ENCODING_HT;
  25.         o->ptr = dict;
  26.     } else {
  27.         serverPanic("Unknown hash encoding");
  28.     }
  29. }
其余的命令实现,底层都是基于ziplist和hashtable的操作,参数解析什么的也都同字符串模型和list模型,这里就不再赘述了。还请大家多提宝贵意见~~~

上一篇:redis源码阅读之链表对象模型
下一篇:redis源码阅读之集合对象