Redis过期时间的设计与实现代码
1. 设置过期时间
Redis 提供了多个命令来设置键的过期时间,如 EXPIRE、PEXPIRE、EXPIREAT 和 PEXPIREAT。这些命令可以以秒或毫秒为单位设置键的过期时间,也可以设置具体的过期时间点。
EXPIRE key secondsPEXPIRE key millisecondsEXPIREAT key timestampPEXPIREAT key milliseconds-timestamp
示例:
2. 过期键的存储结构
每个 Redis 数据库实例(redisDb)中都有一个名为 expires 的字典,用于存储键的过期时间。这个字典将键指针映射到以毫秒为单位的到期时间点。
3. 设置过期时间
通过 setExpire 函数设置键的过期时间。如果键已经存在于 expires 字典中,则更新其过期时间;否则,将其添加到 expires 字典中。
4. 删除过期键的策略
Redis 采用了以下三种策略来删除过期键:
- 惰性删除(Lazy Deletion) :每次访问键时检查其是否过期,如果已过期则删除。这样只在访问键时才进行过期检查,节省了资源。
- 定期删除(Periodic Deletion) :Redis 会周期性地随机抽取一定数量的键进行过期检查,并删除其中已过期的键。这一过程由后台任务定期执行,确保尽可能多的过期键被及时删除。
- 主动删除(Active Expiration) :在内存使用接近最大限制时,会触发主动删除策略,通过扫描所有库的键删除过期数据,以确保内存使用量保持在设定范围内。
Redis 默认采用以下两种删除过期键策略:
惰性删除(Lazy Deletion) :每次访问某个键时检查其是否过期,如果过期则删除。
定期删除(Periodic Deletion) :后台任务定期扫描数据库中的键,随机抽取部分键进行过期检查并删除其中已过期的键。
5. 检查并删除过期键
expireIfNeeded 函数用于检查某个键是否过期,如果过期则删除该键。
getExpire:从expires字典中获取键的过期时间。mstime:返回当前的毫秒时间戳。- 如果键已过期,则调用
dbDelete删除该键,并增加统计计数器stat_expiredkeys。
6. 获取过期时间
getExpire 函数用于获取键的过期时间,如果键没有设置过期时间则返回 -1。
总结
Redis 的过期时间设计与实现包括以下几个关键点:
设置过期时间:通过 EXPIRE、PEXPIRE 等命令设置键的过期时间,并将过期时间存储在
expires字典中。过期字典:每个数据库实例都有一个
expires字典,用于存储键的过期时间。删除策略:
- 惰性删除:每次访问键时检查其是否过期,如果已过期则删除。
- 定期删除:通过后台任务周期性地检测并删除过期键。
- 主动删除:在内存使用接近最大限制时触发,扫描所有键并删除过期键。
定期删除activeExpireCycle函数详细解析
void activeExpireCycle(int type) {
static unsigned int current_db = 0; // 记录上一次处理的数据库索引
static int timelimit_exit = 0; // 用于指示是否超出时间限制
unsigned int j;
// 每次要处理的数据库数量
unsigned int dbs_per_call = CRON_DBS_PER_CALL;
long long start = ustime(); // 开始时间
long long timelimit; // 时间限制
if (type == ACTIVE_EXPIRE_CYCLE_FAST) {
/* Fast cycle: 1 ms */
timelimit = 1000;
} else {
/* Slow cycle: 25% CPU time p. DB / Configurable percentage. */
timelimit = server.hz < 100 ? 1000 : 10;
if (server.active_expire_effort != 1)
timelimit *= server.active_expire_effort-1;
timelimit /= server.dbnum;
timelimit_exit = 0;
}
for (j = 0; j < dbs_per_call; j++) {
redisDb *db = server.db + (current_db % server.dbnum);
current_db++;
int expired, sampled;
do {
long now = mstime();
expireEntry *de;
dictEntry *d;
/* Sample a few keys in the database */
expired = 0;
sampled = 0;
while ((de = dictGetRandomKey(db->expires)) != NULL &&
mstime() - now < timelimit) {
long long ttl = dictGetSignedIntegerVal(de) - mstime();
if (ttl < 0) {
d = dictFind(db->dict, dictGetKey(de));
dbDelete(db, dictGetKey(d));
server.stat_expiredkeys++;
expired++;
}
sampled++;
}
} while (expired > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP / 2);
elapsed = ustime() - start;
if (elapsed > timelimit) {
timelimit_exit = 1;
break;
}
}
}栏 目:Redis
下一篇:详解如何在Windows上配置和使用Redis持久化功能
本文标题:Redis过期时间的设计与实现代码
本文地址:https://www.fushidao.cc/shujuku/781.html
您可能感兴趣的文章
- 12-31深入了解Redis的看门狗机制
- 09-22Redis的Bitmap(位图)详解和命令演示
- 09-22详解如何在Windows上配置和使用Redis持久化功能
- 09-22Redis过期时间的设计与实现代码
- 09-22Redis压缩列表的设计与实现
- 09-22Spring Boot 3.0x的Redis 分布式锁的概念和原理
- 09-22Redis increment 函数处理并发序列号案例
- 09-22深入理解redis删除策略和淘汰策略
- 09-22redis搭建哨兵模式实现一主两从三哨兵


阅读排行
推荐教程
- 09-22详解如何在Windows上配置和使用Redis持久化功能
- 09-22Redis过期时间的设计与实现代码
- 12-31深入了解Redis的看门狗机制
- 09-22Spring Boot 3.0x的Redis 分布式锁的概念和原理
- 09-22redis搭建哨兵模式实现一主两从三哨兵
- 09-22Redis increment 函数处理并发序列号案例
- 09-22深入理解redis删除策略和淘汰策略
- 09-22Redis的Bitmap(位图)详解和命令演示
- 09-22Redis压缩列表的设计与实现




