欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > Redis 过期与淘汰机制全解析

Redis 过期与淘汰机制全解析

2025/5/5 6:29:40 来源:https://blog.csdn.net/weixin_43063493/article/details/147701501  浏览:    关键词:Redis 过期与淘汰机制全解析

概述

Redis 作为一种高性能的内存数据库,提供了数据过期和淘汰策略以管理存储的数据。本文将详细探讨 Redis 中数据失效的基本原理、实现方式,并结合源码进行分析,帮助读者更深入地理解和优化 Redis 的使用。

数据过期机制

过期键的存储方式

Redis 中每个数据库都有一个 expires 字典,用于保存设置了过期时间的键及其对应的过期时间戳。这个字典的作用类似于索引,通过它能够快速判断某个键是否已过期。

typedef struct redisDb {dict *dict;                 // 存储键值对dict *expires;             // 存储键的过期时间// 其他成员...
} redisDb;

定时删除 vs 惰性删除 vs 定期删除

定时删除(Active Expiration / Timer-based Deletion)

定时删除是一种“主动式”删除机制。当用户为一个键设置过期时间时,Redis 会记录该键的过期时间戳,并注册一个定时器,在指定时间到达后自动触发删除操作。虽然这种方法能及时释放内存资源,但可能会导致 CPU 使用率飙升。

// 设置键的过期时间
void setExpire(client *c, robj *key, long long when) {dictEntry *de;de = dictFind(c->db->dict,key->ptr);serverAssertWithInfo(c,key,de != NULL);dictSetVal(c->db->expires,dictAddRaw(c->db->expires,key->ptr,&de),when);
}
惰性删除(Lazy Expiration / On-access Deletion)

惰性删除是一种“被动式”机制。只有在访问某个键时才会检查其是否已经过期,如果已过期则立即删除。这种方式可以显著降低 CPU 的消耗,但代价是部分过期键会长时间保留在内存中。

int expireIfNeeded(redisDb *db, robj *key) {if (!keyIsInHashtable(db->expires, key)) return 0;mstime_t when = getExpire(db, key);mstime_t now = mstime();if (now > when) {deleteExpiredKey(db, key);return 1;}return 0;
}
定期删除(Periodic Expiration)

定期删除是 Redis 主动清理过期键的主要方式之一。Redis 在后台每隔一段时间扫描部分设置了过期时间的键,随机选取一部分进行过期检测,并删除其中已经过期的键。

void activeExpireCycle(int type) {static unsigned int current_db = 0;unsigned int j, iteration = 0;unsigned int dbs_per_call = CRON_DBS_PER_CALL;int start = ustime(), timelimit, noexpire = 0;if (dbs_per_call > server.dbnum) dbs_per_call = server.dbnum;timelimit = 1000000 * ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC / 100;timelimit -= (ustime() - start);for (j = 0; j < dbs_per_call && timelimit > 0 && !noexpire; j++) {redisDb *db = server.db + (current_db % server.dbnum);current_db++;int num = dictSize(db->expires);int slots = ceil(num / 16.0);  // 随机选择 slot 数量while (slots--) {dictEntry *de;long long ttl;if ((de = dictGetRandomKey(db->expires)) == NULL) break;robj *key = dictGetKey(de);ttl = dictGetSignedIntegerVal(de) - mstime();if (ttl < 0) {dbDelete(db, key);}}if ((iteration++ % 10) == 0) {long long elapsed = ustime() - start;if (elapsed >= timelimit) break;}}
}

内存淘汰机制

当 Redis 使用的内存超过 maxmemory 限制时,将会根据配置的淘汰策略来决定移除哪些键值对。常见的淘汰策略包括:

  • volatile-lru:从设置了过期时间的数据集中挑选最近最少使用的数据淘汰。
  • allkeys-lru:从所有数据集中挑选最近最少使用的数据淘汰。
  • volatile-random:从设置了过期时间的数据集中任意选择数据淘汰。
  • allkeys-random:从所有数据集中任意选择数据淘汰。

UML图解 Redis 过期键处理流程

以下是使用 UML 绘制的简化版 Redis 过期键处理流程图,包括定时删除、惰性删除和定期删除的工作流程:

定时删除:

客户端设置键并指定TTL
是否已存在?
更新过期时间
添加到 expires 字典
记录过期时间戳
创建时间事件

惰性删除:

客户端访问键
调用 expireIfNeeded 方法
是否存在于 expires 字典中?
当前时间 > 过期时间?
删除键-惰性删除
正常处理请求

定期删除:

serverCron 周期调用
调用 activeExpireCycle 方法
遍历数据库
随机取样部分键
是否过期?
删除键-定期删除
保留键

结语

Redis 通过一系列复杂的机制来管理数据的生命周期和内存使用情况,旨在提供高效的数据管理和查询服务。理解这些基本概念和机制对于优化性能、避免内存溢出等问题至关重要。希望这篇文章能为你提供有价值的参考信息,帮助你更好地利用 Redis 提供的功能。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词