服务器中的数据库
redisServer
redis是内存数据库。所以,一个redis数据库,就对应了一个结构体。
struct redisServer {
// 一个数组,保存着服务器中的所有数据库
redisDB *db;
// 服务器中数据库的数量
int dbnum;
}
客户端通过select [0-15] 来选择一个redis实例中的哪个数据库。
数据库默认的个数是16个。
数据库结构体.pngredisDB
下面来看看redisDB
typedef struct redisDB {
// 数据库键空间,dict字典保存着数据库中的所有键值对
dict *dict;
// 过期字典,保存着所有键的过期时间
dict *expires;
}
键空间和用户所看见的数据库是直接对应的。
dict的键,就是数据库的key。字符串对象。
dict的值,就是数据库的value,robj对象。
如果对数据执行如下命令
select.png
可以看到数据库从6号变成了8号。当前8号的数据库键空间字典就是这样的
键空间.png
对数据库的增删改查,都是对dict这个map的增删改查。
对数据里面的数据结构的增删改查,比如对book的增删改查,都是对book对应的map的增删改查。
键的过期时间
设置过期时间有4个命令:
- expire 后面加 秒
- pexpire 后面加 毫秒
- expireat 后面加 秒级时间戳 表示直到这个时间点
- pexpireat 后面加 毫秒级时间戳 表示直到这个时间点
该四个方法,最终都会转换成
pexpireat执行
过期时间保存在过期字典里。
过期字典的key,就是数据库的key。
过期字段的value,就是毫秒精度的unix时间戳,表示过期时间。
redis通过当前时间 和 过期时间戳 的时间差,来判断是否过期。
现在知道了过期时间是怎么存的了,那过期的键怎么删除呢???
-
定时删除
到了过期时间就删除。在设置键的过期时间时,创建一个回调事件,当过期时间达到时,由时间处理器自动执行键的删除操作。
好处:内存友好。
缺点:对cpu不友好,会有大量的事件cpu资源用在了删除上。 -
惰性删除
在对key操作的时候,发现key是过期的,才删除。
好处:对cpu友好。
缺点:对内存不友好,会导致内存泄露,这个key没有再用到,就永远不会删除了。 -
定期删除
定时任务,定期删除。
缺点:很难确定执行的时长和频率。
redis实际使用的是惰性删除和定期删除。通过配合使用这两种策略,服务器可以在cpu和内存之间取得一个很好的平衡。
具体怎么做的呢
比如redis-3.0.0中hz默认值是10,表示每秒钟调用10次后台清理任务。
典型的方式为,redis每秒做10次如下的步骤:
- 随机测试100个设置了过期时间的key
- 删除所有发现的已过期的key
- 若删除的key超过25个则处重复步骤1
总结:redis会在hz的频率下(n次每秒),会在一定时间限制内尽可能多的删除过期key。
网友评论