Redis基本数据类型:哈希(hash)
Redis内部使用两种结构来实现hash
- 压缩列表(ziplist)
- 哈希表(hashtable)
1. 压缩列表(ziplist)
Redis每次创建哈希类型的时候,都会先使用默认ziplist。
使用这种结构时,redisObject.encoding = OBJ_ENCODING_ZIPLIST
robj *createHashObject(void) {
unsigned char *zl = ziplistNew();
robj *o = createObject(OBJ_HASH, zl);
o->encoding = OBJ_ENCODING_ZIPLIST;
return o;
}
当ziplist不满足下面条件时,会自动转成哈希表
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
2. 哈希表(hashtable)
使用这种结构时,redisObject.encoding = OBJ_ENCODING_HT
先来简单介绍下hashtable用到的结构:
dict struct
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
long rehashidx;
unsigned long iterators;
} dict;
- ht[2] - 默认建立两个hashtable,正常时都使用ht[0],当需要移动hashtable时,会逐个把ht[0]里面的节点拷贝到ht[1]。如果此时有更新操作,也会直接对ht[1]进行修改。当ht[0]全部移动到ht[1]里面后,将两个hashtable进行切换
- rehashidx - 移动hashtable标识,-1表示没有发生移动
ht = dictIsRehashing(d) ? &d->ht[1] : &d->ht[0];
dictht struct
typedef struct dictht {
dictEntry **table;
unsigned long size;
unsigned long sizemask;
unsigned long used;
} dictht;
- table - 字典数组,记录每个节点信息,初始化为NULL
- size - 字典数组的大小,初始化为0
- sizemask - size-1,初始化为0
- used - 字典数组已经使用的个数,初始化为0
static void _dictReset(dictht *ht)
{
ht->table = NULL;
ht->size = 0;
ht->sizemask = 0;
ht->used = 0;
}
当插入节点大于空闲节点数时(size-used),就会对hashtable进行扩容,大概的步骤:
- 创建一个新的hashtable,size是原来的2倍(如果原来的size是0,会使用默认大小4)
- 将字典的ht[1]替换为新创建的hashtable
- 将ht[0]里面的节点移动到ht[1]
- 移动完成,切换ht[1]到ht[0]
dictEntry struct
typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next;
} dictEntry;
- key - 节点索引
- val - 节点值
- next - 指向下一个节点的指针,当索引相同时,使用“拉链法”处理冲突
3. command
- HDEL - Delete one or more hash fields
- HEXISTS - Determine if a hash field exists
- HGET - Get the value of a hash field
- HGETALL - Get all the fields and values in a hash
- HINCRBY - Increment the integer value of a hash field by the given number
- HINCRBYFLOAT - Increment the float value of a hash field by the given amount
- HKEYS - Get all the fields in a hash
- HLEN - Get the number of fields in a hash
- HMGET - Get the values of all the given hash fields
- HMSET - Set multiple hash fields to multiple values
- HSCAN - Incrementally iterate hash fields and associated values
- HSET - Set the string value of a hash field
- HSETNX - Set the value of a hash field, only if the field does not exist
- HSTRLEN - Get the length of the value of a hash field
- HVALS - Get all the values in a hash
上一篇:Redis学习小计(5) - 基本数据类型:列表(list)
下一篇:Redis学习小计(7) - 基本数据类型:集合(set)