一个Reids服务由多个Redis数据库组成。
redis的数据库实际上是一个dict
Redis 服务 数据结构
typedef struct redisServer {
....
redisDb *db;//数组,保存服务中的所有数据库
int dbnum;//服务器中数据库数量,由配置文件的database决定
....
}
typedef struct redisDb {
...
dict *dict;
dict * expires;//失效时间数据库
}
切换数据库
每一个redis客户端连接服务的时候,redis都会生成 一个redisClient 结构体来记录客户端的相关信息。
typedef struct redisClient {
...
redisDb *db;//当前使用的数据库
...
}
执行select 1 ,实际上就是切换db指针指向的对象
数据库的kv
k始终为redisString对象
v为实际存储的redis对象.例如 lPush l1 v1,则存储的对象是redis_list.
过期
命令
expire k ttl:多少s后失效expireat k timestamp:在什么时间点失效pexpire k ttl:多少ms后失效pexpireat k timestamp
实际上都是调用pexpireat命令.其他的命令会做一系列的转化.
过期时间实际上是使用一个dict * expires map保存的
删除
-
惰性删除:过期后不立即删除,而是等到访问或者其他操作的时候在判断是否过期然后在进行删除.
-
定期(限定每次执行删除操作的时间)删除:如何保证删除是全部遍历,而不是饿死某些键?使用一个数据库记录当前正常处理的数据库序号.本质上就是按顺序删除的。
-
redis周期性调用redis.c/serverCron函数 -
serverCron会调用activeExpireCycle函数- 使用全局变量
curent_db记录当前处理的数据库,从0开始,每调用一次后curent_db+1,直到和数据库总数相等的时候,重新从0开始 - 每次执行删除操作的时候,从当前数据库随机选择一定个数的
key,判断其是否失效,如果失效就执行删除操作。(这个会不会和用户重新设置有效期的操作并发?)
- 使用全局变量
-
-
惰性删除和定期删除也会写
AOF文件 -
从服务器不会执行惰性删除,目的是为了主从数据完全一致。