同样的hash类型对象也有两种编码方式,一种是压缩列表,一种是哈希表哈希对象默认创建的是压缩列表编码方式,当达到一定条件后会转换成哈希编码方式
#define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define REDIS_ENCODING_HT 2 /* Encoded as hash table */
// 创建一个哈希对象
robj *createHashObject(void) {
unsigned char *zl = ziplistNew();
robj *o = createObject(REDIS_HASH, zl);
o->encoding = REDIS_ENCODING_ZIPLIST;
return o;
}
//常见的条件有以下这些
#define REDIS_HASH_MAX_ZIPLIST_ENTRIES 512
#define REDIS_HASH_MAX_ZIPLIST_VALUE 64
server.hash_max_ziplist_entries 保存的键值数量小于默认值512
server.hash_max_ziplist_value 键值的长度都小于默认值64字节
// 具体的转换函数为hashTypeConvert
void hashTypeConvert(robj *o, int enc) {
if (o->encoding == REDIS_ENCODING_ZIPLIST) {
hashTypeConvertZiplist(o, enc);
} else if (o->encoding == REDIS_ENCODING_HT) {
redisPanic("Not implemented");
} else {
redisPanic("Unknown hash encoding");
}
}
// 将REDIS_ENCODING_ZIPLIST编码对象转成REDIS_ENCODING_HT
void hashTypeConvertZiplist(robj *o, int enc) {
redisAssert(o->encoding == REDIS_ENCODING_ZIPLIST);
if (enc == REDIS_ENCODING_ZIPLIST) {
} else if (enc == REDIS_ENCODING_HT) {
hashTypeIterator *hi;
dict *dict;
int ret;
hi = hashTypeInitIterator(o);
dict = dictCreate(&hashDictType, NULL);
while (hashTypeNext(hi) != REDIS_ERR) {
robj *field, *value;
field = hashTypeCurrentObject(hi, REDIS_HASH_KEY);
field = tryObjectEncoding(field);
value = hashTypeCurrentObject(hi, REDIS_HASH_VALUE);
value = tryObjectEncoding(value);
ret = dictAdd(dict, field, value);
if (ret != DICT_OK) {
redisLogHexDump(REDIS_WARNING,"ziplist with dup elements dump",
o->ptr,ziplistBlobLen(o->ptr));
redisAssert(ret == DICT_OK);
}
}
hashTypeReleaseIterator(hi);
zfree(o->ptr);
// 转换编码方式和新的字典
o->encoding = REDIS_ENCODING_HT;
o->ptr = dict;
} else {
redisPanic("Unknown hash encoding");
}
}
基于版本3.0.0版本,点击下载https://download.redis.io/releases/redis-3.0.0.tar.gz
本文地址,https://www.ccagml.com/?p=424