typedef struct dictEntry { // 键 void *key; // 值 union { void *val; uint64_t u64; int64_t s64; } v; // 指向下个哈希表节点,形成链表 struct dictEntry *next; } dictEntry;
key
属性保存着键值对中的键,而 v
属性则保存着键值对中的值,其中键值对的值可以是一个指针,或者是一个 uint64_t
整数,又或者是一个 int64_t
整数。
next
属性是指向另一个哈希表节点的指针,这个指针可以将多个哈希值相同的键值对连接在一次,以此来解决键冲突(collision)的问题。
next
指针,将两个索引值相同的键
k1
和
k0
连接在一起
Redis字典具有以下特点:
- Redis字典的底层实现为哈希表,
- 每个字典使用两个哈希表,一般情况下只使用 0 号哈希表,只有在 rehash 进行时,才会同时使用 0 号和 1 号哈希表。
- 哈希表使用链地址法来解决键冲突的问题。
- 自动 Rehash 扩展或收缩哈希表。
- 对哈希表的 rehash 是分多次、渐进式地进行的
/*
* hash节点
*/
typedef struct dictEntry {
//键
void *key;
//值
union {
void *val;
uint64_t u64;
int64_t s64;
} v;
//指向下一个节点
struct dictEntry *next;
} dictEntry;
typedef struct dictht {
//桶
dictEntry **table;
//指针数组大小
unsigned long size;
//指针数组掩码,用于计算索引值
unsigned long sizemask;
//hash表现有节点数量
unsigned long used;
} dictht;
typedef struct dict {
//类型处理函数
dictType *type;
//类型处理函数私有值
void *privdata;
//两个hash表
dictht ht[2];
//rehash标示,为-1表示不在rehash,不为0表示正在rehash的桶
int rehashidx; /* rehashing not in progress if rehashidx == -1 */
//当前正在运行的安全迭代器数量
int iterators; /* number of iterators currently running */
} dict;
http://redissrc.readthedocs.io/en/latest/datastruct/dict.html
http://redisbook.com/preview/dict/datastruct.html
typedef struct dictht { // 哈希表数组 dictEntry **table; // 哈希表大小 unsigned long size; // 哈希表大小掩码,用于计算索引值 // 总是等于 size - 1 unsigned long sizemask; // 该哈希表已有节点的数量 unsigned long used; } dictht;
table
属性是一个数组,数组中的每个元素都是一个指向 dict.h/dictEntry
结构的指针,每个 dictEntry
结构保存着一个键值对。
size
属性记录了哈希表的大小,也即是 table
数组的大小,而 used
属性则记录了哈希表目前已有节点(键值对)的数量。
sizemask
属性的值总是等于
size - 1
,这个属性和哈希值一起决定一个键应该被放到
table
数组的哪个索引上面