php过期键的定期删除策略,Redis中的过期键删除策略

我们知道在Redis数据库中,我们可以为相应的键设置过期时间

那么在相应键的过期时间到了,我们要通过什么方法来回收相应的键呢?

对于上面的问题,我们有以下三种不同的删除策略

定时删除:在设置键过期时间的同时,创建一个定时器,让定时器在过期时间来临的时候,立即删除相应的键。

惰性删除:我们先不管当前键是否过期,在使用的时候检查一下当前键是否已经过期,如果过期就立即删除当前键。

定期删除:系统每隔一定的时间对数据库做一次检查,删除里面的过期键。

注:以上的三种删除策略里面,第一和第三种被称为主动删除策略,第二种被称为被动删除策略。

定时删除

定时删除对于内存是最友好的,通过使用定时器,可以保证过期的键会尽可能快的被删除,并释放其占用的内存。

但是在过期键比较多的情况下,删除过期键可能会占用占用相当一部分的CPU(如果这个时候内存并不是很紧张但是有大量的命令在请求CPU处理),所以说这种策略是对CPU不友好的。

除此之外,创建定时器需要用到Redis服务器中的时间事件,而当前时间事件的实现方式是无序链表,创建一个事件的时间复杂度为O(n) —— 并不能高效的处理大量时间时间。

因此,要让服务器创建大量的定时器从而时间定时删除策略,当前来说还并不现实。(引用自《Redis设计与实现》)

惰性删除

惰性删除对于CPU是最友好的,其只在当前键的时候才会做其过期检查,这可以保证删除过期键的操作只会在非做不可得情况下才会进行,从而使CPU不会在删除其他无关紧要的键上面浪费时间。

非常明显,这种策略对于内存是不友好的。

同时还可能会造成内存泄漏——比如有的键可能永远也不会再使用了,这样子就永远存在内存中不会被释放。而Redis服务器又是非常依赖内存的,所以这是一个非常不好的结果。

定期删除

上面的两种策咯都有明显的缺点

定时删除:可能会占用大量的CPU时间,影响服务器的响应时间和吞吐量

惰性删除:可能会浪费大量的内存,导致内存泄漏

而定期操作是前面两种策略的一个折中

通过每隔一定的时间删除过期键,并通过限制删除操作的时长和频率来减少对CPU影响(相对定时删除)

定期删除不会导致有的键因为很长时间才会使用或者永不使用(但是已经过期)而带来的内存浪费甚至内存泄漏问题

定期删除策略需要考虑的问题有两个:删除操作执行的时长,删除操作执行的频率

所以说,如果采取定期删除策略的话就需要根据当前项目的情况,合理的设置删除操作的时长和频率,从而使系统的性能达到最优。

那么在Redis数据库中使用的是哪种删除策略呢?—— 惰性删除和定期删除

惰性删除策略的实现

在Redis的源码中是使用db.c/expireIfNeed()函数实现的

/** * 检查 key 是否已经过期,如果是的话,将它从数据库中删除。 * * 返回 0 表示键没有过期时间,或者键未过期。 * * 返回 1 表示键已经因为过期而被删除了。 */

int expireIfNeeded(redisDb *db, robj *key) {

/* 取出键的过期时间 */

mstime_t when = getExpire(db,key);

mstime_t now;

/* 如果没有过期时间 */

if (when < 0) return 0;

/* 服务器loading的时候暂时先不工作 */

if (server.loading) return 0;

/* 获取当前时间*/

now = server.lua_caller ? server.lua_time_start : mstime();

/* 如果当前的是从(Slave)机 * 0 if we think the key should be still valid, * 1 if we think the key is expired at this time. * */

if (server.masterhost != NULL) return now > when;

/* 如果未过期,返回 0 */

if (now <= when) return 0;

/* 删除键 */

server.stat_expiredkeys++;

propagateExpire(db,key,server.lazyfree_lazy_expire);

notifyKeyspaceEvent(NOTIFY_EXPIRED,

"expired",key,db->id);

return server.lazyfree_lazy_expire ? dbAsyncDelete(db,key) :

dbSyncDelete(db,key);

}

命令调用expireIfNeeded()的过程如图所示

Created with Raphaël 2.1.0

开始

所有读写数据可的命令(GET,LRANGE,SADD等)

所操作的键是否已经过期?

删除键

执行实际的命令流程

yes

no

定期删除策略的实现

过期键的定期删除策略由expire.c/activeExpireCycle()函数实现,每当服务器周期性操作server.c/serverCron函数执行时,activeExpireCycle()函数就会被调用,在短时间内,分多次便利服务器中的数据库,从数据库的expires字典中随机检查一部分键的过期时间,并删除其中的过期键。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值