Redis服务器将所有数据库都保存在服务器状态redis.h/redisServer结构的db数组中,db数组的每一项都是一个redisDb结构,每个redisDb代表一个数据库。
struct redisServer {
redisDb *db;
int dbnum;//该值是由服务器配置的database选项决定,默认值是16
};
每个Redis客户端都有自己的目标数据库,默认情况下Redis客户端的目标数据库为0号数据库。但是客户端可以用SELECT来切换目标数据库。
struct redisClient {
redisDb *db;//记录客户端当前正在使用的数据库
}redisClient;
redisClient.db 指针指向redisServer.db数组中的一个元素。如下所示:
redisDb结构的dict字典保存了数据库中的所有键值对,
typedef struct redisDb [
dict *dict;
dict *expires; //保存数据库中所有键的过期时间
}redisDb;
例如执行下面一系列的操作后
数据库的存储空间如9-4所示:
使用Redis命令对数据库进行读写时,服务器不进会对建空间执行指定的读写操作,还会有额外的操作:
- 读取一个键之后,服务器会根据键是否存在来更新服务器的建空间命中(hit)次数或不中(miss)次数。
- 读取一个键之后,服务器会更新键的LRU时间,这个值可以用于计算键的闲置时间。使用OHJECT idletime <key> 查看key的闲置时间
- 在读取一个键时发现键已经过期,则先删除这个过期键。再执行余下操作。
- 如果客户端使用WATCH监视某个键,则在对键的修改后,会将其标志为脏(dirty)
- 每次修改一个键之后,都对脏键计数器的值加1,这个计数器会出发服务器持久化以及复制操作。
- 如果开启了通知功能,则修改之后会按照配置发送数据库通知。
设置键的生存或过期时间,过期字典保存数据库中所有键的过期时间。expires字典:
- 过期字典的键是一个指针,指向建空间某个键对象。
- 过期字典值是一个long long类型整数,一个毫秒精度的UNIX时间戮
下图展示了带过期时间的redisDb结构:
过期键删除策略,
- 定时删除:对内存最友好,使用定时器,可以保证过期键会尽可能快的被删除,并释放内存。缺点是,对于CPU不友好,当过期键比较多的情况,删除过期键核能占用相当一部分CPU时间,党对于CPU资源紧张的情况下无疑会对服务器的响应时间和吞吐造成影响。
- 惰性删除:对于CPU来说是友好的,只会在取出键的时候在检查是否过期,缺点是对内存不友好。
- 定期删除:他是对上面两种策略的一种折中,每隔一段时间执行一次删除过期键操作,并限制删除操作的市场和频率来减少对CPU时间的影响,具体执行市场和频率需要根据情况来定。
复制模式: 当服务器运行在复制模式下时,从服务器的过期键删除动作由主服务器控制;
- 主服务器删除一个键之后,会显示的向所有从服务器发送DEL命令
- 从服务器在执行客户端发送的读命令,即使碰到过期键也会返回信息
- 从服务器只有收到主服务器发来的DEL命令才会删除过期键
数据库通知:
是Redis2.8版本新增加的功能,这个功能可以让客户端通过订阅给定的频道或模式,来获知数据库中键的变化,以及数据库中命令执行情况。