Redis 内存回收

一、Redis 内存回收的整体架构

Redis 是一个 内存数据库,所有键值都存放在 RAM 中。
为了避免无限增长导致 OOM(Out Of Memory),Redis 有三大类内存回收机制:

1. 键过期删除策略(主动回收)

  • 惰性删除(Lazy Deletion)
  • 定期删除(Tuned Scanning)

2. 内存淘汰策略(当内存达到最大值 maxmemory)

  • noeviction / allkeys-* / volatile-* 系列

3. 内存碎片与 jemalloc 管理(内存再利用)

  • jemalloc arena 管理
  • active defrag(主动碎片整理)

这三者共同对 Redis 内存进行回收和优化。


二、键过期删除(Expires)

Redis 支持给 key 设置 TTL(time-to-live)。

EXPIRE key 10
SET key value EX 10

Redis 的过期键删除不是精确实时触发,而是采用三种机制组合:


1. 惰性删除(Lazy Deletion)

触发时机:

  • 当客户端访问某个 key
  • Redis 检查它是否已经过期
  • 过期 → 立即删除

示例:

GET key
→ 发现 key 已过期 → 删除并返回 nil

优点:

  • 简单、高效
  • 不访问不过期,不浪费 CPU

缺点:

  • 如果 key 很久不被访问
  • 会一直占用内存(内存泄漏风险)

所以 Redis 还必须搭配第二种机制。


2. 定期删除(Active Expire Cycle)

Redis 每 100ms(server.hz 参数控制)随机抽取部分带过期时间的 key:

流程:

  1. 随机扫描一部分 db.expires 字典
  2. 删除其中已经过期的 key
  3. 如果过期比例 > 25%,继续扫描(最多执行 25ms)

优点:

  • 避免过期键长期堆积
  • 平衡 CPU 占用

缺点:

  • 不是实时、高精度的删除
  • 大量过期键可能延迟删除

3. 主动删除 + 从节点同步

在执行命令期间,如果命令涉及访问过期 key:

  • 主线程执行惰性删除
  • 命令传播到从节点和 AOF 时也写入 DEL 操作

三、内存淘汰策略(maxmemory 触发)

当 Redis 达到 maxmemory 时,就会触发内存淘汰策略。

配置:

maxmemory 2gb
maxmemory-policy allkeys-lru

Redis 内置 8 种策略:


1. 不淘汰

● noeviction

内存满时写命令(SET/LPUSH/ZADD)直接报错。


2. 只淘汰带过期时间的键(volatile-*)

策略说明
volatile-lru淘汰最近最少使用的 expire key
volatile-lfu淘汰访问最少的 expire key
volatile-ttl淘汰剩余生存时间最短的 key
volatile-random随机淘汰一个 expire key

如果没有带 TTL 的 key → 和 noeviction 一样报错。


3. 淘汰所有键(allkeys-*)

策略说明
allkeys-lru淘汰最近最少使用的 key
allkeys-lfu淘汰访问最少的 key(Redis 4+)
allkeys-random随机淘汰一个 key

企业生产最常用:

allkeys-lru
allkeys-lfu(访问热点分布更均衡)

四、Redis 的内存分配器:jemalloc

Redis 默认使用 jemalloc 来管理内存。

jemalloc 特点:

  • 多个 arena,减少锁竞争
  • 对小块内存管理更高效
  • 减少内存碎片
  • 速度快(Redis 高性能关键之一)

Redis 里每个 key/结构体 要走 jemalloc 的分配逻辑。


四、内存碎片问题

Redis 内存碎片率:

info memory → mem_fragmentation_ratio

当碎片率 > 1.5 或 2 时可能需要处理。

Redis 支持主动碎片整理:

active-defrag yes

作用:

  • 后台线程合并碎片块
  • 迁移 key 的内存布局
  • 减少物理内存占用

适用于高更新写 load 的业务。


五、Redis 内存回收的整体流程图

在这里插入图片描述


六、实际场景中的内存回收案例

情况 1:大量 key 同时过期(如 0 点定时刷新)

效果:

  • 惰性删除无法及时回收
  • 定期扫描也跟不上
  • Redis 内存激增

解决:

  • 设置随机 TTL(打散过期时间)
  • 使用 expire 命令 + 随机偏移

情况 2:大量数据更新导致碎片暴涨

解决:

active-defrag yes

适合 key 更新频繁的系统(订单系统、排行榜系统)。


情况 3:内存爆满导致频繁淘汰、QPS 急剧下降

解决:

  • 分析 key 大小(大 key 拆分)
  • 调整 maxmemory-policy
  • 提高 Redis 内存
  • 使用 Redis Cluster 分片

七、面试高频问题(含标准答案)

1. Redis 的过期删除策略是什么?

答:惰性删除 + 定期删除 双策略。


2. Redis 内存淘汰策略有哪些?

8 种:

  • noeviction
  • volatile-lru / lfu / ttl / random
  • allkeys-lru / lfu / random

3. 为什么 Redis 采用定期删除而不是主动删除?

因为主动删除是 O(n) 扫描,会阻塞主线程。


4. LRU 与 LFU 区别?

  • LRU:最近最少使用
  • LFU:访问次数最少

LFU 更适合热点数据分布不均的业务。


5. Redis 为什么使用 jemalloc?

  • 更快
  • 内存碎片更少
  • 多线程 arena 更适合 Redis 高并发

6. active-defrag 是如何工作的?

后台线程迁移 key 内部结构,使碎片合并。


八、总结(背诵版)

Redis 内存回收 = 过期清理 + 内存淘汰 + 内存碎片整理

  • 过期键:惰性删除 + 定期删除
  • 内存限制:maxmemory-policy
  • 内存管理:jemalloc
  • 碎片修复:active-defrag
  • 大 key 问题:拆分 + 批量删除

Redis 内存管理体系既高效又安全,是持久高性能的重要基础。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值