结构
前面的文章我们已经了解到 Redis 的对象系统以及底层数据结构的实现。接下来的章节,我们会深入数据库的实现。
redisServer(服务端结构):
struct redisServer {
// ...
redisDb *db; // 一个数组,保存着服务器中的所有数据库
int dbnum; // 数据库的数量
// ...
}
(dbnum在配置文件中,默认数值是16)
redisClient(客户端结构):
struct redisClient {
redisdb *db; // 客户端当前正在使用的数据库,指向redisServer中db数组中的某一个
}
redisDb(数据库结构):
struct redisDb {
dict *dict; // 数据库键空间,保存着所有的键值对
}
一些数据库的维护操作
- 更新键的命中次数和未命中次数(如 GET 命令取一个不存在的键时,未命中次数就会+1)
- 更新键的LRU时间
- 惰性删除键
- 标记脏键(客户端使用watch命令监视某个键的状态,如果键的值被修改了,就会被标记为脏数据)
- 脏键计数器值 + 1
- 数据库通知
(不理解的下文或者后续的章节都会讲解)
关于键的过期时间
struct redisDb {
// ...
dict *expires; // 过期字段,保存着键的过期时间
// ...
}
expires的键是一个指针,指向过期的字符串键对象。
expires的值是一个long类型的时间戳,表示键的过期时间。
过期键的判定
- 判断键是否在过期字典中
- 判断当前时间是否大于键的过期时间
过期键的删除策略
Redis采用定期删除 + 惰性删除的策略。
惰性删除:每一个Redis的命令在执行前都会进行过期键的检查,如果发现该键过期,则立即删除。(如果没有命令对过期键进行访问,只能依靠定期删除的策略)。
定期删除:Redis周期性操作的一个环节,分批遍历每个数据库,然后随机取出一些键进行过期检查。
AOF、RDB和复制功能对过期键的处理
AOF和RDB都是Redis的持久化策略,下一个章节会介绍。
复制是Redis集群的功能,就是将一个Redis中的内容,复制到另一个Redis上。
RDB
生成RDB文件的时候,如果键过期了,那么不会被写入文件中。
服务器启动时,如果是主服务器,会检查键是否过期,过期的键会被忽略掉,不会被载入数据库。
如果是从服务器,无论键是否过期,都会被载入数据库。
AOF
如果键已经过期了,对AOF文件没有任何影响,因为AOF文件中存储的是写命令嘛。当过期键被定期删除或者惰性删除后,会向文件中追加键的删除命令(DEL)。
AOF重写的过程中,会对键进行过期检查,已经过期的键是不会保存到重写后的AOF文件中。
复制
在Redis的集群模式中,有且仅有一个主服务器,可以有N多个从服务器。
所有的写操作在主服务器上进行,所有的读操作在从服务器上进行。(读写分离)
数据的同步依靠主服务器向从服务器发送命令实现。(相当于这时候,主服务器就是从服务器的客户端)
按照这个机制,如果键过期了,会向所有的从服务器发送DEL命令,删除对应的过期键。在没有收到主服务器发送的DEL命令时,即使键已经过期了,也不会执行惰性删除或者定期删除操作。
数据库通知
其实就是【发布订阅】功能的实现,在后续的章节中会详细说明。
2024.10.25
writeBy kaiven