服务器中的数据库
// redis.h/redisServer
// 服务器状态
struct redisServer {
// 服务器的数据库数量
int dbnum;
redisDb *db;
// 过期字典
dict *expires;
// ...
}
// 数据库状态
typedef struct reidsDb {
dict *dict;
} redisDb;
在初始化服务器时,程序会根据 dbnum 属性来决定应该创建多少个数据库。
dbnum 属性的值由服务器配置的 database 选项决定,默认为 16。
切换数据库
Redis 客户端的目标数据库为 0 号数据库。
typedef struct reidsClient {
// 记录客户端当前正在使用的数据库
redisDb *db;
// ...
}
SELECT 命令实现原理
修改 redisClient.db 指针,让它指向服务器中不同的数据库,从而实现切换目标数据库的功能。
数据库键空间
读写键空间时的维护操作
-
服务器会根据键是否存在来更新服务器的键空间命中次数和键空间不命中次数。
redis stats // keyspace_hits // keyspace_misses
-
服务器会更新键的 LRU 时间,代表键的闲置时间
object idletime key
-
如果服务器在读取一个键时发现已过期,服务器会先删除这个过期键,然后执行余下的其他操作。
-
如果有客户端使用 watch 命令监视某个键,在对该键修改之后,会将这个键标记为脏,从而让事务程序注意到这个键已经被修改。
-
服务器每次修改一个键之后,都会对脏键计数器的值加1,这个计数器会触发服务器的持久化以及复制操作。
-
如果服务器开启了数据库通知功能,在对键修改之后,服务器会按配置发送相应的数据库通知。
设置过期时间
expire <key> <ttl>
pexpire <key> <ttl>
expire <key> <timestamp>
pexpire <key> <timestamp>
移除过期时间
persist <key>
剩余时间
ttl <key>
pttl <key>
过期键删除策略
- 定时删除
- 在设置键过期时间的同时,创建一个定时器,到键的过期时间立即执行删除操作。
- 对内存友好,对 CPU 时间不友好。
- 定时器用到 Redis 服务器的时间事件,时间事件的实现方式是无序链表,不能高效处理大量时间事件。
- 惰性删除
- 定期删除
- 每次执行,从一定数量的数据库中取出一定数量的随机键检查。
服务器配置的 notify-keyspace-events 决定服务器发送通知的类型
- AKE:发送所有类型的键空间通知和键事件通知
- AK:发送所有类型的键空间通知
- AE:发送所有类型的键事件通知
- A$:只发送和字符串键有关的键空间通知
- El:只发送和列表键有关的键事件通知