字典,是一种用于保存键值对的抽象数据结构。在字典中,一个键对应一个值。字典中的每个键都是独一无二的,程序可以再字典中根据键查找与之关联的值,更新值,或者删除整个键值对。字典经常作为一种数据结构在高级语言里,C语言中没有内置这种数据结构,所以Redis构建了自己的字典实现。
Redis的字典使用哈希表作为底层实现,一个哈希表里面可以哈希节点,每个哈希节点就保存了字典中的一个键值对
Redis 所使用的哈希表由 dictht 结构定义
typedef struct dictht { // 哈希表数组,数组中的每个元素都是一个指向 dictEntry 结构的指针,每个 dictEntry 都保存着一个键值对 dictEntry **table; // 哈希表大小,也是哈希表数组的大小 unsigned long size; // 哈希表大小掩码,用于计算索引值。总是等于size-1 unsigned long sizemask; // 该哈希表已有节点数量 unsigned long used; } dictht;
一个大小为4的空哈希表
哈希表节点使用 dictEntry 结构表示,每个 dictEntry 结构都保存着一个键值对
typedef struct dictEntry { // 键 void *key; // 值 union { void *val; uint64_t u64; int64_t s64; double d; } v; // 指向下一个哈希表节点,形成链表。可以将多个哈希值相同的键值对链接再一起,来解决哈希冲突问题。 struct dictEntry *next; } dictEntry;
两个哈希值相同的键
Redis 中的字典由 dict 结构实现
typedef struct dict { // 类型特性函数,指向 dictType 的指针,每个 dictType 结构保存了用于操作特定类型键值对的函数 dictType *type; // 私有数据,保存了需要传给类型特定函数的可选参数 void *privdata; // 哈希表,一般情况下只使用ht[0]哈希表,ht[1]只会在 rehash 时使用 dictht ht[2]; // rehash索引,当rehash不在进行时,值为-1 long rehashidx; /* rehashing not in progress if rehashidx == -1 */ } dict; typedef struct dictType { // 计算哈希值的函数 uint64_t (*hashFunction)(const void *key); // 复制键的函数 void *(*keyDup)(void *privdata, const void *key); // 复制值的函数 void *(*valDup)(void *privdata, const void *obj); // 对比键的函数 int (*keyCompare)(void *privdata, const void *key1, const void *key2); // 销毁键的函数 void (*keyDestructor)(void *privdata, void *key);、 // 销毁值的函数 void (*valDestructor)(void *privdata, void *obj); } dictType;
普通状态下没有进行rehash的字典