在系统设计中,作为重要的内存数据库与缓存中间件,Redis 的数据过期机制(TTL)是其内存管理的核心。它不仅仅是设置一个时间那么简单,背后涉及到高效的清理策略,直接影响着应用的稳定性和资源利用率。掌握其原理,对于设计合理的缓存策略至关重要。
我们以字符串类型为例,先回顾一下与过期时间(TTL)相关的基本操作命令。
一、Redis TTL 相关基本操作命令
# 1. 设置一个普通键值对
SET user "zhangsan"
# 2. 给键设置60秒过期
EXPIRE user 60
# 3. 查看剩余过期时间(返回约50+秒)
TTL user
# 4. 移除过期时间
PERSIST user
# 5. 再次查看(返回-1,永不过期)
TTL user
# 6. 设置key的时候附带过期时间
SETEX user1 20 "zhangsan"
实际操作效果如下图所示,可以清晰地看到设置、查询和移除过期时间的过程:

二、Redis 过期键的清理机制(核心)
一个关键的认知是:Redis 不会在键过期的瞬间立即删除它。如果立即删除,在大量键同时过期时会对性能造成冲击。为此,Redis 采用了三种协同工作的机制来清理过期键。
1. 惰性删除(Lazy Expiration)
- 原理:只有当客户端主动尝试访问一个键时,Redis 才会检查该键是否过期。如果已过期,则立即删除它并返回空值(nil)。这是一种“按需检查”的策略。
- redis-cli 验证:
# 设置键10秒过期
SETEX user1 10 "zhangsan"
# 10秒内访问:返回zhangsan(未过期)
GET user1
# 10秒后访问:返回(nil)(触发惰性删除)
GET user1
# 再次查看键是否存在:返回0(已删除)
EXISTS user1
下图展示了 SETEX 命令执行后,键在过期前后被访问的不同结果:

- 优点:最大限度地节省了 CPU 资源,只在必要时才进行清理操作。
- 缺点:如果大量过期键长期不被访问,它们会一直占用宝贵的内存空间,造成事实上的“内存泄漏”。仅靠惰性删除无法完全解决问题。
2. 定期删除(Periodic Expiration)
- 原理:为了弥补惰性删除的不足,Redis 会周期性(默认每100ms)地主动检查并删除一批过期键。它并非扫描所有键,而是随机抽取一部分设置了过期时间的键进行检查。
- 核心规则:
- 每次抽取的键数量和检查的总时长都有严格上限,以确保不会阻塞主线程。
- 系统会自适应调整频率:当过期键比例较高时,后续检查会更频繁。
相关的配置参数(在 redis.conf 中):
# 每100ms执行一次定期删除(默认开启)
hz 10
# 每次定期删除的最大耗时(默认250ms)
active-expire-effort 1
- 优点:在 CPU 和内存使用上取得了平衡,能够定期清理掉那些不被访问的过期键。
- 缺点:由于是随机采样,可能存在“漏网之鱼”,部分过期键可能不会被本轮抽查到。
3. 内存淘汰(Memory Eviction)
惰性删除和定期删除是日常的清理机制。而当 Redis 内存使用达到 maxmemory 配置的上限时,就会触发最后的“防线”——内存淘汰。
- 原理:当内存不足时,Redis 会根据配置的淘汰策略(
maxmemory-policy)删除键以释放空间。淘汰时优先考虑已过期的键,如果过期键不够,则会根据策略淘汰未过期的键。
- 常见淘汰策略(可通过
CONFIG GET maxmemory-policy 命令查看):
volatile-lru:从已设置过期时间的键中,淘汰最近最少使用(LRU)的。
volatile-ttl:从已设置过期时间的键中,淘汰剩余生存时间(TTL)最短的。
allkeys-lru:从所有键中淘汰最近最少使用的。
noeviction:默认策略。不淘汰任何键,当内存满时,新写入操作会返回错误。
选择合适的内存淘汰策略,是构建健壮缓存系统的重要一环,这属于高并发系统设计中的关键考量。关于更多系统设计与架构知识,可以在技术社区进行深入探讨。
总结
Redis 的数据过期是一个由 “惰性删除” 、 “定期删除” 和 “内存淘汰” 三者共同构成的复合机制。理解这个机制,有助于我们:
- 合理设置过期时间:避免大量键在同一时刻过期,给定期删除造成压力。
- 正确预估内存容量:知道惰性删除可能带来的内存驻留,预留足够缓冲。
- 选择合适的淘汰策略:根据业务场景(如缓存还是持久存储)配置
maxmemory-policy。
在实际开发中,尤其是在设计会话缓存、验证码缓存等场景时,深刻理解并运用好 TTL 机制,能让你的应用更加稳定高效。希望这篇文章能帮助你深入理解 Redis 的过期策略。如果你想了解更多数据库或中间件的实践细节,欢迎访问 云栈社区 与更多开发者交流。
|