字典(dictionary), 又名映射(map)或关联数组(associative array), 是一种抽象数据结构, 由一集键值对(key-value pairs)组成, 各个键值对的键各不相同, 程序可以添加新的键值对到字典中, 或者基于键进行查找、更新或删除等操作。
字典的主要用途有以下两个:
- 实现数据库键空间(key space)
- 用作 Hash 类型键的底层实现之一
实现数据库键空间
Redis 是一个键值对数据库, 数据库中的键值对由字典保存: 每个数据库都有一个对应的字典, 这个字典被称之为键空间(key space)。
当用户添加一个键值对到数据库时(不论键值对是什么类型), 程序就将该键值对添加到键空间; 当用户从数据库中删除键值对时, 程序就会将这个键值对从键空间中删除; 等等。
举个例子,执行 FLUSHDB 可以清空键空间里的所有键值对数据:
redis> FLUSHDB
OK
执行 DBSIZE 则返回键空间里现有的键值对:
redis> DBSIZE
(integer) 0
还可以用 SET 设置一个字符串键到键空间, 并用 GET 从键空间中取出该字符串键的值:
redis> SET number 10086
OK
redis> GET number
"10086"
redis> DBSIZE
(integer) 1
用作 Hash 类型键的底层实现之一
Redis 的 Hash 类型键使用以下两种数据结构作为底层实现:
- 字典
- 压缩列表
因为压缩列表比字典更节省内存, 所以程序在创建新 Hash 键时, 默认使用压缩列表作为底层实现, 当有需要时, 程序才会将底层实现从压缩列表转换到字典。
当用户操作一个 Hash 键时, 键值在底层就可能是一个哈希表。
字典的实现
实现字典的方法有很多种:
- 链表或数组,时间复杂度高
- 哈希表,兼顾高效和简单
- 平衡树,复杂和稳定高效
在众多可能的实现中, Redis 选择了高效、实现简单的哈希表,作为字典的底层实现。
/*
* 字典
*
* 每个字典使用两个哈希表,用于实现渐进式 rehash
*/
typedef struct dict {
// 特定于类型的处理函数
dictType *type;
// 类型处理函数的私有数据
void *privdata;
// 哈希表(2 个)
dictht ht[2];
// 记录 rehash 进度的标志,值为 -1 表示 rehash 未进行
int rehashidx;