PHP redis 计时器,Redis之key过期定时器实现

本文深入探讨了Redis的过期策略,包括定时过期、惰性过期,并分析了为何不采用立即过期策略的原因。通过查看源码,了解到Redis在3.0版本中采用的是定时和访问过期的混合策略,其中定期删除通过activeExpireCycle函数进行,而惰性过期则在每个读写命令执行前检查。EXPIRE等相关命令用于设置key的过期时间,且在主节点上设置过期时间并发送pub通知。
摘要由CSDN通过智能技术生成

用Redis时,有用到EXPIRE、PEXPIRE、SETEX之类命令去设置key的过期时间。从2.8版开始还可以去做简单的定时器服务。

原先也没太具体去了解Redis的过期实现方式,但心中总觉得有块石头没放下,于是乎开3.0的源码去翻看了。

过期策略有3种:立即过期、定时过期、访问过期(惰性过期)。但看了源码后,发现Redis并没采用立即过期的策略,而是采用 定时过期 和 访问过期 混合方式。使用立即过期的话,Linux环境下在Redis进程里会有很多timerfd,在几十万个Key这种数量级开始,对cpu是很大的负担。

redis.h

在redis.h文件里有redisDb结构体

typedef struct redisDb {

dict *dict;

dict *expires;

......

}

expires这属性是存放当前db有过期时间的键,使用hash数据结构。

定期删除策略

代码在redis.c的activeExpireCycle函数,需要传个type参数,用以区分是用“快速模式”还是“正常模式”。

在“正常模式”下,会遍历每一个编号下的库,然后最多随机获取20个带过期时间的key(20是宏ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP的默认值),倘若key太多则直接return了。接着调用redis.c/activeExpireCycleTryExpire函数尝试去删除它,能删除成功则再发送expired的pub通知给订阅者即可。定期删除的定时时长是100ms。

惰性过期

代码分布在所有读写命令里,如SET、GET、TTL、SADD、HGET...等。每次调用这些命令的实际执行前,都会调用db.c/expireIfNeeded函数来删除过期键,在删除之前,也会发送expired的pub通知。

EXPIRE/PEXPIRE/SETEX的作用?

这几个命令的真正作用是设置过期时间,如EXPIRE命令的处理在db.c/expireCommand开始,然后将过期时间单位从秒转换成毫秒,接着判断是否存在从节点,最后传播删除了的expired key(pub del)。在主节点则设置过期时间,是在宏代码里去设置值(联合体结构),最后在pub expire的通知。

后记

redis是单线程的,但个人觉得在pub方面可以用另一条线程去处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值