Redis服务器数据库的实现

Redis服务器数据库的实现

redis服务器将所有数据库都保存在redis.h/redisServer结构体中的Db数组中,每个Db数组都是一个redis.Db结构。初始化数据库时会根据redisServer结构中的dbnum属性来决定数据库的多少。

struct redisServer{
	...
	redisDb *db;//一个数组,保存者服务器中的所有数据库
	int   dbnum;//服务器的数据库数量根据配置文件生成
    ...
}
typedef struct redisDb{
	...
	dict *dict;//数据库的键空间保存数据库的所有键值对
	dict *expires;//过期字典
    ...
}

对数据库的键值操作实际就是对一个字典的键值操作。Redis的所有key-value值都存在于这个大的字典中,默认16个数据库就存在16个字典

如果需要切换数据库,redisClient结构的Db属性,一个指向redisDb的指针,切换实际就是对这个指针进行操作。

键的生存时间或过期时间原理

EXPIRE或PEXPIRE 命令是将生存时间设置为多少秒和毫秒

EXPIREAT或PEXPIREAT命令是将过期时间设置为所输入的时间戳 这四个命令最终都转换为PEXPIREAT,它们的过期时间都是一个UNIX时间戳。

保存过期时间的是一个存在于上文redisDB结构中的字典,这个字典被称为过期字典,value为longlong类型,用来保存key所对应的过期UNIX时间戳。

PERSIST移除过期时间实际是删除过期字典中的这个键

怎么判断键是否过期?

1.先检查这个键是否存在于过期字典:如果存在,取得过期时间时间戳

2.检查当前时间戳与过期时间戳得大小判断是否过期。

TTL或者PTTL如果返回大于等于0就说明未过期。

Redis过期键的删除策略

惰性删除+定期删除两种

惰性删除:只有在取出键进行使用时才会对键进行过期检查并且判断删除

定期删除:每相隔一定时间进行判断删除

Redis为什么不单一使用一种策略进行删除?

如果使用惰性删除:如果存在很多过期键但没有被访问,会非常的消耗内存。

如果使用定期删除:难以直接确定定期删除的时长和频率,如果太过于频繁就会退化为定时删除,以至于将cpu时间过多的消耗在删除过期键上面。如果执行频率过少就会退化为惰性删除,出现浪费内存的情况。

所以Redis使用惰性删除+定期删除两种策略。

实现:
惰性删除策略:

所有读写数据库的Redis命令在执行前都会调用expireIfNeeded函数对输入键进行检查进行判断是否过期,如果过期删除键之后继续执行相对应得命令,如果未过期则直接执行相应输入得命令。

定期删除策略:

定期删除的函数activeExpireCycle存储在serverCron函数中,这个函数会在过期字典中随机抽取一定量的键进行检查判断,并且记录位置。

eg:第一次随即查询0号数据库,第二次就会随机1号。

RDB、AOF对过期键的处理

SAVE和BGSAVE会对过期键进行检查,已过期的键不会被保存到RDB文件中,载入RDB文件时主服务器会对过期字典及进行检查,从服务器不论是否过期全部载入(主从模式:数据库状态同步时会将从服务器数据库清空)

AOF中键过期或会输入DEL命令。在执行AOF重写的过程中也会对数据库中的键进行检查,已经过期的键不会被写入

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值