Redis 字典(Dictionary)是其用于存储键值对的核心数据结构之一,实现了高效、可伸缩的键值查找和更新。Redis 的字典是通过哈希表(hashtable)实现的,具体实现细节如下:
-
哈希表结构:
Redis 字典的底层是两个哈希表dictht
的结构,通常称之为哈希表1和哈希表2。每个dictht
结构体包含以下字段:typedef struct dictht { dictEntry **table; // 哈希表数组,每个元素指向一个链表 unsigned long size; // 哈希表大小,即数组的长度 unsigned long sizemask; // 哈希表大小掩码,用于计算索引值 unsigned long used; // 已使用节点(键值对)的数量 } dictht;
-
哈希表节点(dictEntry):
每个键值对都封装在一个dictEntry
结构体中,形成链表:typedef struct dictEntry { void *key; // 键 union { void *val; // 值 uint64_t u64; int64_t s64; } v; struct dictEntry *next; // 指向下个哈希冲突节点的指针 } dictEntry;
-
哈希函数:
Redis 通过哈希函数将键转换成哈希表数组的索引。当键插入字典时,会使用哈希函数计算出对应的数组索引,若发现索引位置已经有其他键存在(哈希冲突),则将新键值对挂载到该位置链表的头部。 -
扩容与缩容:
当字典负载因子(used / size)超过一定阈值时,Redis 会触发哈希表的扩容操作,扩大哈希表的大小并重新哈希所有键值对。反之,若负载因子过低,Redis 也可能进行缩容操作以节约内存。 -
API 操作:
Redis 提供了一系列 API 用于操作字典,包括但不限于:dictCreate()
:创建新的字典对象。dictAdd()
或dictReplace()
:向字典中添加或替换键值对。dictFind()
:查找给定键是否存在及其对应值。dictDelete()
:删除键值对。dictResize()
:调整哈希表大小,处理扩容或缩容。dictGetRandomKey()
:随机获取字典中的一个键。dictIteratorInit()
和相关迭代函数:遍历字典中的所有键值对。
通过这种设计,Redis 字典能够在大规模数据集上提供接近 O(1) 的平均查找、插入和删除复杂度,同时具有良好的空间效率。