当前位置: 首页 > news >正文

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 提供的功能。

相关文章:

  • 【操作系统】吸烟者问题
  • 【深度解析】DCN-V2:Google新一代特征交叉网络,如何实现推荐系统精准度飞跃?
  • python hasattr()
  • C++基础算法9:Dijkstra
  • Spring AI 实战:第七章、Spring AI Advisor机制之记忆大师
  • 前端面试每日三题 - Day 24
  • 入门Linux 进程:进程概念、进程状态与进程地址空间
  • NPP库中libnppitc模块介绍
  • 49认知干货:产品的生命周期及类型汇总
  • MYSQL数据库突然消失
  • C语言:文件操作
  • 谷歌 NotebookLM 支持生成中文播客
  • 【项目篇之统一硬盘操作】仿照RabbitMQ模拟实现消息队列
  • 【SQL触发器、事务、锁的概念和应用】
  • 计算机网络:详解TCP协议(四次握手三次挥手)
  • Free Draft Model!Lookahead Decoding加速大语言模型解码新路径
  • 主机电路安全防护系统哪个厂家做
  • 2025年01月03日美蜥(杭州普瑞兼职)一面
  • 递归下降算法
  • ART 下 Dex 加载流程源码分析 和 通用脱壳点
  • 库里22分赢下抢七大战,火箭十年难破“火勇大战”的魔咒
  • 旅游特种兵们,这个五一“躲进”书吧
  • 案件发回重审,李在明参选韩总统之路再添波折
  • 澎湃读报丨央媒头版集中刊发社论,庆祝“五一”国际劳动节
  • 应急管理部派出工作组赴山西太原小区爆炸现场指导救援处置
  • 日菲同意扩大安全合作,外交部:反对任何在本地区拉帮结派的做法