数据库键空间
Redis 是一个键值对(key-value pair)数据库服务器, 服务器中的每个数据库都由一个 redis.h/redisDb 结构表示, 其中, redisDb 结构的dict 字典保存了数据库中的所有键值对, 我们将这个字典称为键空间(key space):
typedef struct redisDb {
// ...
// 数据库键空间,保存着数据库中的所有键值对
dict *dict;
// ...
} redisDb;
键空间和用户所见的数据库是直接对应的:
- 键空间的键也就是数据库的键, 每个键都是一个字符串对象。
- 键空间的值也就是数据库的值, 每个值可以是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象在内的任意一种 Redis 对象。
举个例子, 如果我们在空白的数据库中执行以下命令:
redis> SET message "hello world"
OK
redis> RPUSH alphabet "a" "b" "c"
(integer) 3
redis> HSET book name "Redis in Action"
(integer) 1
redis> HSET book author "Josiah L. Carlson"
(integer) 1
redis> HSET book publisher "Manning"
(integer) 1
那么在这些命令执行之后, 数据库的键空间将会是图 IMAGE_DB_EXAMPLE 所展示的样子:
- alphabet 是一个列表键, 键的名字是一个包含字符串 "alphabet" 的字符串对象, 键的值则是一个包含三个元素的列表对象。
- book 是一个哈希表键, 键的名字是一个包含字符串 "book" 的字符串对象, 键的值则是一个包含三个键值对的哈希表对象。
- message 是一个字符串键, 键的名字是一个包含字符串 "message" 的字符串对象, 键的值则是一个包含字符串 "hello world" 的字符串对象。
所以对数据库的增删改查也是对键空间字典的增删改查。
重点
- Redis 服务器的所有数据库都保存在 redisServer.db 数组中, 而数据库的数量则由 redisServer.dbnum 属性保存。
- 客户端通过修改目标数据库指针, 让它指向 redisServer.db 数组中的不同元素来切换不同的数据库。
- 数据库主要由 dict 和 expires 两个字典构成, 其中 dict 字典负责保存键值对, 而 expires 字典则负责保存键的过期时间。
- 因为数据库由字典构成, 所以对数据库的操作都是建立在字典操作之上的。
- 数据库的键总是一个字符串对象, 而值则可以是任意一种 Redis 对象类型, 包括字符串对象、哈希表对象、集合对象、列表对象和有序集合对象, 分别对应字符串键、哈希表键、集合键、列表键和有序集合键。
- expires 字典的键指向数据库中的某个键, 而值则记录了数据库键的过期时间, 过期时间是一个以毫秒为单位的 UNIX 时间戳。
- Redis 使用惰性删除和定期删除两种策略来删除过期的键: 惰性删除策略只在碰到过期键时才进行删除操作, 定期删除策略则每隔一段时间, 主动查找并删除过期键。
- 执行 SAVE 命令或者 BGSAVE 命令所产生的新 RDB 文件不会包含已经过期的键。
- 执行 BGREWRITEAOF 命令所产生的重写 AOF 文件不会包含已经过期的键。
- 当一个过期键被删除之后, 服务器会追加一条 DEL 命令到现有 AOF 文件的末尾, 显式地删除过期键。
- 当主服务器删除一个过期键之后, 它会向所有从服务器发送一条 DEL 命令, 显式地删除过期键。
- 从服务器即使发现过期键, 也不会自作主张地删除它, 而是等待主节点发来 DEL 命令, 这种统一、中心化的过期键删除策略可以保证主从服务器数据的一致性。
- 当 Redis 命令对数据库进行修改之后, 服务器会根据配置, 向客户端发送数据库通知。