该功能主要通过expireIfNeeded 这个函数来实现的,redis对于需要设置超时的key,放到了单独的一个hash中,所以只要检测这个超时hash就可以了。
//检查是否超时,超时了那么就删除
int expireIfNeeded(redisDb *db, robj *key) {
time_t when = getExpire(db,key);
//该key没有设置超时
if (when < 0) return 0; /* No expire for this key */
//正在载入
/* Don't expire anything while loading. It will be done later. */
if (server.loading) return 0;
//如果是slave, 它不需要直接进行删除的,它的删除有master来控制的,但是它需要调用者一个返回直:是不是超时.
/* If we are running in the context of a slave, return ASAP:
* the slave key expiration is controlled by the master that will
* send us synthesized DEL operations for expired keys.
*
* Still we try to return the right information to the caller,
* that is, 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 time(NULL) > when;
}
//存在但未超时
/* Return when this key has not expired */
if (time(NULL) <= when) return 0;
//删除并通知文件和slave
/* Delete the key */
server.stat_expiredkeys++;
propagateExpire(db,key);
return dbDelete(db,key);
}
对不同的情况,做不同的处理,我们再来看看propageteExpire函数
void propagateExpire(redisDb *db, robj *key) {
robj *argv[2];
argv[0] = createStringObject("DEL",3);
argv[1] = key;
incrRefCount(key);
//只有在appendonly开启的时候,才进行操作
if (server.appendonly)
feedAppendOnlyFile(server.delCommand,db->id,argv,2);
if (listLength(server.slaves))
replicationFeedSlaves(server.slaves,db->id,argv,2);
decrRefCount(argv[0]);
decrRefCount(argv[1]);
}
如果开启了appendonly,那么从append文件中进行删除。
如果存在slaves,那么从slave中进行删除