文章目录
隐藏
redis key过期策略
ChatGPT said:
ChatGPT
在 Redis 中,Key 过期策略是用来管理缓存中键的有效时间和内存的释放。Redis 提供了多种策略来处理过期 Key,包括主动和被动的方式,以及不同的内存淘汰策略。
1. 过期策略
Redis 的过期策略主要分为两类:惰性删除和定期删除。
1.1 惰性删除(Lazy Deletion)
- 当对某个 Key 进行访问(如
GET
、SET
、DEL
等操作)时,Redis 会检查该 Key 是否过期。如果过期,则删除该 Key。 - 优点:惰性删除不会浪费 CPU 资源,因为只有在访问时才会检查是否过期。
- 缺点:如果过期的 Key 没有被访问,内存将一直被占用,可能会造成内存泄露的风险。
1.2 定期删除(Periodic Deletion)
- Redis 会每隔一段时间(默认 100 毫秒)随机抽取一些设置了过期时间的 Key,检查它们是否过期,如果过期则删除。
- 优点:定期删除可以减少内存的占用。
- 缺点:需要在性能和内存之间做权衡,过于频繁会增加 CPU 的消耗,过于稀疏又会导致内存中存在过多的过期 Key。
2. 内存淘汰策略
当 Redis 的内存达到上限时,会按照配置的淘汰策略删除部分 Key。常见的内存淘汰策略有:
2.1 noeviction
- 默认策略,不淘汰任何 Key。当内存不足时会拒绝写入请求,返回错误。
- 适用于只读场景或明确的内存上限。
2.2 allkeys-lru
- 基于最近最少使用算法(LRU,Least Recently Used)淘汰所有 Key 中最不常用的 Key。
- 适用于缓存场景,能更好地利用内存。
2.3 volatile-lru
- 仅淘汰设置了过期时间的 Key 中最不常用的 Key。
- 适用于需要优先保留永久数据的场景。
2.4 allkeys-random
- 随机淘汰所有 Key 中的某些 Key。
- 适用于需要快速释放内存且没有明确缓存策略的场景。
2.5 volatile-random
- 随机淘汰设置了过期时间的 Key。
- 适用于需要随机释放内存的场景。
2.6 volatile-ttl
- 仅淘汰设置了过期时间的 Key,优先淘汰 TTL(Time-To-Live,存活时间)最短的 Key。
- 适用于更倾向于释放即将过期的缓存数据。
3. 设置过期时间
在 Redis 中可以通过以下命令为 Key 设置过期时间:
EXPIRE key seconds
:设置 Key 的过期时间为seconds
秒。PEXPIRE key milliseconds
:设置 Key 的过期时间为milliseconds
毫秒。EXPIREAT key timestamp
:设置 Key 的过期时间为指定时间戳。TTL key
:查看 Key 的剩余存活时间。PERSIST key
:移除 Key 的过期时间,使其成为永久 Key。
4. 实际应用场景
- 缓存失效:为缓存数据设置过期时间,防止长期占用内存。
- 会话管理:为用户会话设置过期时间,实现自动登出功能。
- 分布式锁:通过设置过期时间实现分布式锁的自动释放。
5. 优化建议
- 合理设置 TTL:为不同类型的数据设置合理的 TTL,可以有效避免内存溢出。
- 监控和调优:使用 Redis 的
INFO stats
命令监控过期 Key 的数量和内存占用情况,根据需求调整淘汰策略。 - 选择合适的淘汰策略:根据业务需求选择合适的内存淘汰策略,确保在高并发场景下的高效和稳定。
总结
Redis 通过过期策略和内存淘汰策略保证了缓存的有效利用和内存的高效管理。在实际应用中,需要根据业务需求和性能要求合理配置这些策略。
4o
You said:
Redis 存在很多过期 key, 没有删除,是什么原因
ChatGPT said:
ChatGPT
Redis 中存在大量过期的 Key 但没有被删除,可能有以下几个原因:
1. 惰性删除(Lazy Deletion)的局限
- 惰性删除是在访问 Key 时才检查是否过期,删除过期的 Key。
- 如果过期的 Key 在过期后没有被访问,那么 Redis 就不会主动删除它们,导致内存中依然存在这些过期 Key。
- 解决方法:可以通过手动访问这些 Key 来触发删除,或者使用 Redis 的
SCAN
命令遍历整个数据库以触发过期检查。
2. 定期删除(Periodic Deletion)不彻底
- Redis 每隔 100 毫秒会随机抽取一部分设置了过期时间的 Key 进行检查和删除,但它不是一次性删除所有过期 Key。
- 如果过期的 Key 数量很多,或者内存负载较高,Redis 定期删除的数量可能不足,导致很多过期的 Key 没有被及时删除。
- 解决方法:可以调整 Redis 的
hz
配置参数(默认是 10),增大定期删除的频率,来加快过期 Key 的清理速度。
3. 内存不足导致的定期删除受限
- 当 Redis 内存接近最大限制时,Redis 会将更多资源分配给内存管理,而不是删除过期的 Key。这样可以导致 Redis 没有足够的时间去处理过期 Key。
- 解决方法:可以调整 Redis 的内存限制参数(
maxmemory
),同时配合合适的内存淘汰策略来释放内存。
4. CPU 负载过高
- 如果 Redis 服务器的 CPU 负载较高,定期删除的操作可能会受到限制,从而导致过期 Key 的清理速度变慢。
- 解决方法:可以优化 Redis 的其他操作(如减少慢查询、降低并发量等),给定期删除腾出更多的 CPU 资源。
5. 持久化对过期 Key 清理的影响
- 如果 Redis 开启了 RDB 或 AOF 持久化,持久化过程中 Redis 会优先保证数据的写入和同步,可能会影响定期删除过期 Key 的频率。
- 解决方法:优化持久化配置,减少持久化带来的性能影响。
6. 设置了不合适的淘汰策略
- Redis 支持多种内存淘汰策略(如
noeviction
、allkeys-lru
、volatile-lru
等)。如果策略设置不当,可能导致 Redis 更倾向于保留某些 Key,而不是删除过期的 Key。 - 解决方法:根据业务需求调整合适的淘汰策略,比如使用
volatile-lru
、volatile-ttl
等策略,以优先删除设置了过期时间的 Key。
7. 过期时间的设置不合理
- 如果大量的 Key 过期时间相近,Redis 的定期删除可能无法及时清理这么多过期 Key。这会导致一段时间内过期的 Key 无法被彻底清理。
- 解决方法:可以在业务逻辑中对过期时间进行随机化设置,避免过期时间集中在某一个时间点。
如何检测和解决过期 Key 的积压?
- 使用
INFO
命令查看过期 Key 的数量:- 通过命令
INFO keyspace
查看当前数据库中过期 Key 的数量。 - 也可以通过
TTL
命令来查看某个具体 Key 的剩余时间,来检查它是否已经过期。
- 通过命令
- 手动清理过期 Key:
- 可以使用 Redis 的
SCAN
命令遍历整个数据库,触发过期检查。 - 也可以通过 Redis 的 Lua 脚本,遍历所有 Key 并手动删除过期的 Key。
- 可以使用 Redis 的
- 调整定期删除频率:
- 修改配置文件中的
hz
参数,或者在启动时用--hz
参数设置定期删除频率(推荐值:20-50),以提高定期删除的效率。
- 修改配置文件中的
- 内存和 CPU 调优:
- 适当增加 Redis 服务器的 CPU 和内存,或者分片部署 Redis 集群,分担单个实例的压力。
总结
Redis 中的过期 Key 未被删除,通常是因为惰性删除的触发条件不满足,或者定期删除不够频繁、受限等因素。通过合理配置 Redis 参数、优化内存淘汰策略、分布式部署等方式,可以有效解决这个问题。