Redis对于过期Key的处理和思考

304 阅读3分钟

Redis对于过期Key的处理

背景

在实际工作使用中有一个场景需要通过一个倒计时来触发一些通知,当时没有经过太多考虑就想到redis的key有自动过期时间,因此使用redis的key的自动到期作为了触发通知的方案。

但是在实际使用中间歇性的就出现,通知触发不及时导致的发送慢,有的时候还出现了倒计时都结束很久了,但是并没有触发任何通知的逻辑(DB和日志记录都没有相关信息)。起初怀疑是网络问题后面随着问题一直出现,在通过排除后发现和redis的Key过期处理方式有关。

分析

本着万事不决看文档的思路,通过结合官方文档之后发现,我们遇到的问题确实和redis处理过期key的方式有关,文档的详细可以通过链接来看,这里简单说下redis是怎么处理过期key的。

redis处理过期key分为两个大类:

  • 主动处理:redis会定期从过期key里面检测一部分,并且删除掉;
  • 被动处理:当key过期之后redis并没有及时清理key,而是等到客户端调用之后才发现key已经过期然后处理掉过期key;

当时看到文档这样描述的时候,就理解了为什么我们有的明明倒计时已经完成了,但是没有发送通知,应该是这些key没有在主动模式里面被检测到,因此最后过期了。

接下来看下redis对于主动处理过期key的方式,redis会在每秒进行10次以下检查:

  1. 先随机获取20个带有过期时间的key;
  2. 删除掉已经过期的;
  3. 如果处理完步骤2之后,仍然有超过25%的key是已经过期的,那么重复步骤1

也就是说按照这个逻辑处理,在redis的所有key里面最终总会有接近25%的key即使过期也不会被主动处理掉。到这里就解释了为什么在我们业务里面有的倒计时到最后都没有发送通知。

那么还有一个问题,为什么有的倒计时当时通知了但是过了很久之后才通知,实效性降低了很多导致业务上也无法接受。这里就出现了另一问题过期key的事件处理。

通过官方文档可以发现:redis的key过期之后基本上就会生成过期事件,这时候按理来说客户端就可以通过监听来处理redis key过期的事件

然而由于redis的key过期之后,由于主动处理和被动处理的机制有时候key并不会被立刻删除,因此也就没有过期事件发生,所以业务代码也就会出现没触发或者触发晚了的情况。

思考

1.由于redis的处理过期key偏随性和不确定性,因此对于实效性和准确性要求高的场景不能使用redis的key自动过期策略来作为延时处理的方案。

2.对于延时的方案可以考虑消息队列中的延时消息,如果场景很特殊那么还需要再结合实际场景思考处理。