redis 的内存清理

redis.png

一个示例

❓ redis中,set一个值,有效期为 3600 秒,这个值会什么时候释放?

常规理解为,在 3600 秒到期后,redis服务会自动清除,

也就意味着,redis需要有一个机制,每隔一个时间极短的时间段去扫描所有的key,判断是否到期并删除,这种开销是巨大的

过期删除

对于设置了过期时间的 key,删除有两个机制共同管理

✅ 惰性删除(访问时释放)

触发时机:当客户端访问该 key(如执行 GET、TTL、EXISTS 等命令)时。

行为:Redis 检测到该 key 已过期,立即物理删除该 key,释放内存,然后返回 nil。如果没被访问,即使过了 100 秒,key 仍可能留在内存中。

📌 关键点:如果这个 key 过期后再也没有被访问过,它会一直占用内存,直到被其他机制清理。

✅ 定期删除(后台定时释放)

触发条件:Redis 后台每隔 100ms(默认配置)会启动一次(后台任务)定期扫描任务,随机抽取部分带过期时间的 key 检查。

行为:从所有设置了过期时间的 key 中随机抽取 n 个;删除其中已过期的 key;

📌 关键点:这是一个概率性、非实时的清理过程。所以你设置了过期时间的 key 可能在这一轮扫描中,没扫描到,会在以后的任意时间点(比如 10.2s、12s、甚至更久)被清理,取决于是否被抽中。

对于后台任务执行间隔配置为

# 就这一行配置,默认就是 10
hz 10

hz 10代表的含义为:Redis 每秒钟会执行 10 轮"后台定时任务"循环,用来完成以下工作:

  1. 扫描并清理已过期的 key(这就是我们用到的)。
  2. 关闭空闲超时的客户端连接。
  3. 更新 serverCron 里的各类统计信息、触发 AOF 重写/RDB 保存的阈值判断等。

hz的值调的越高,服务负载越大

❓ 还有另外一种场景,当服务器内存使用超过健康阈值时,如何更好的调优?

比如服务器内存 16G,现在 Redis 用了 15.9G 了,在没钱升级配置的情况下,如何保障能够继续 set get 使用

淘汰策略

这里先说明一个参数 # maxmemory <bytes> ,官方说明为

# Set a memory usage limit to the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.

意思就是,

设置内存使用限制为指定的字节数。当达到内存限制时,Redis将尝试根据选择的清除策略,删除键;

如果Redis无法根据策略移除键,或策略设置为 **noeviction**,则 Redis 将开始对会占用更多内存的命令(如SET、LPUSH等)返回错误,但只读命令如GET)依旧可以正常使用。

这个解释很清晰了,该配置默认是注释的,也就意味着 Redis 默认允许无限使用内存!!!

在设置了该参数后,可以根据不同种规则来清除一些 redis 的 key,从而降低内存

参数配置示例

# 限制 Redis 最大使用内存为 4GB
maxmemory 4gb
 
# 或者使用字节
maxmemory 4294967296

换句话来说,当 Redis 设置了 maxmemory 参数后,可选择下面任何一个方式,来优化内存,具体选择哪种(这里面学问大的很,比方说热点数据、不常用数据的取舍),看你自己

策略名称 说明 备注
noeviction 默认策略:内存不足时,新写入会报错(OOM command not allowed) 不淘汰,默认值
allkeys-lru 从所有 key 中淘汰最近最少使用(Least Recently Used)的 key LRU算法
volatile-lru 从设置了过期时间的 key 中淘汰 LRU key LRU算法
allkeys-lfu 从所有 key 中淘汰最不经常使用(Least Frequently Used)的 key LFU算法
volatile-lfu 从设置了过期时间的 key 中淘汰 LFU key LFU算法
allkeys-random 从所有 key 中随机淘汰 随机算法
volatile-random 从设置了过期时间的 key 中随机淘汰 随机算法
volatile-ttl 从设置了过期时间的 key 中淘汰剩余生存时间(TTL)最短的 key TTL优先

这里补充个题外话,LRU与LFU算法区别

✅ LRU 最近最少使用的被淘汰。
实现方式:内部可能通过链表的特性,尾部淘汰吧,具体实现不清楚

✅ LFU 最不经常使用的被淘汰。
实现方式:每个 key 有一个访问频率计数器(logc),具体实现不清楚

📌 LFU示例:对于热点数据维度的保护策略

一个 key 每天被访问 100 次(长期热点),LFU 会保留它。
一个 key 只被访问一次,即使是"最近"访问,LFU 也会优先淘汰。

回顾

  1. 过期删除方式中的惰性删除定期删除为两种不同机制,组合起来构成删除机制
  2. 过期删除机制 和 淘汰策略 两种之间独立运行,互补干涉
  3. 淘汰策略只有在设置maxmemory参数,且内存达到该值时才生效
  4. 目前来说,不支持多种策略同时生效
  5. 技术不是一尘不变的,Redis 不同版本是有差异的
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容