Redis 字典(Dictionary)是其核心数据结构之一,它以高效的方式存储键值对,支撑着Redis的数据库、哈希、集合、有序集合等多种高级数据结构的底层实现。字典主要通过两个哈希表(dictht
)实现,允许在执行操作时进行扩容和再哈希,以应对键值对数量的增长。每个哈希表由数组(buckets)组成,数组中的每个元素都是指向dictEntry
结构的指针,dictEntry
中包含了键和值的指针,以及指向下一个哈希冲突节点的指针(形成链表)。
字典的实现细节
- 哈希表(
dictht
):Redis 字典使用两个哈希表,一个作为活跃表(active),另一个作为备用表(rehashing),在需要扩容或缩容时,通过渐进式rehash减少阻塞时间。 - 哈希冲突解决:采用开链法处理冲突,即在哈希值相同的bucket中,使用链表链接多个
dictEntry
。 - 字典操作:包括但不限于插入(
dictAdd
)、查找(dictFind
)、删除(dictDelete
)等,这些操作都会考虑是否正在rehash,并相应地更新两个哈希表。 - 内存管理:Redis 使用自己的内存管理策略,如
zmalloc
等函数分配和管理字典及其内部元素所需的内存。
迭代器(Iterator)
Redis 提供了迭代器来遍历字典中的键值对,这对于备份、复制、持久化以及其他需要遍历数据的场景至关重要。迭代器的实现保证了即使在遍历过程中字典被修改(如rehash操作),也能正确无误地遍历所有元素。
- 迭代器接口:通过
dictIterator
结构和相关函数(如dictGetIterator
创建迭代器,dictNext
移动到下一个元素)提供迭代功能。 - 安全遍历:迭代器在rehash过程中能够正确工作,通常通过维护当前遍历的哈希表指针和索引来确保,即使字典的结构发生变化,也能安全地继续遍历。
源码分析
在Redis源码中,字典的定义和接口主要位于dict.h
文件,而具体实现则在dict.c
中。想要深入理解字典及迭代器的实现,可以关注以下几个关键点:
dict.h
中dict
结构定义和相关操作函数原型。dict.c
中具体的操作函数实现,包括rehash逻辑和迭代器的实现细节。- SDS和链表等其他数据结构的使用,因为它们经常作为字典中键值的存储形式。
通过阅读这些源码文件,可以了解到如何高效地插入、查找、删除键值对,以及在字典结构变化时如何维护迭代器的正确性。