渐进式 rehash 与双表过渡
Redis 的哈希表在扩容或缩容时不会一次性搬迁,而是保留新旧两张表并存、分批渐进迁移:迁移窗口内每次操作顺带搬一点数据,键查找要同时查两张表。代价是这段窗口内该字典的内存会短时接近翻倍,这正是「内存台阶式上涨后停在新的基线上」的常见来源。另外,执行持久化 fork 期间字典扩缩容会被推迟到更高阈值才触发,写密集时段也可能看到额外的内存增长。
基本信息
| 触发条件 | 装载因子越界(元素数与桶数之比) |
|---|---|
| 过程 | 新旧两表并存,分批搬迁 |
| 内存影响 | 窗口内短时接近翻倍 |
| fork 期间 | 扩缩容被推迟,写量大时更明显 |
| 观测命令 | INFO memory、MEMORY STATS |
| 关键字段 | used_memory 与 used_memory_peak |
| 判断依据 | 上涨后是否停在新基线 |
典型使用场景
- 内存出现台阶式上涨,判断是 rehash 还是数据增长
- 排查内存尖峰是否与持久化时间窗重合
- 容量规划时为大字典预留额外水位
- 解释同一份数据在两台实例上内存差异明显的现象
- 压测写入海量小键时观察内存曲线的形态变化
- 评估是否值得把大 hash 拆分,降低单次扩容幅度
观测与判断
观测与判断
redis-cli INFO memory | grep -E 'used_memory:|used_memory_peak'
redis-cli MEMORY STATS | head -20 # 看各类结构的分布
redis-cli DBSIZE # 键总量是否同步增长
redis-cli INFO stats | grep -E 'expired_keys'
redis-cli INFO persistence | grep -E 'rdb_bgsave_in_progress'
redis-cli INFO server | grep -E 'redis_version'内存曲线形态对照
| 形态 | 常见解释 | 处置 |
|---|---|---|
| 台阶式上涨后走平 | 字典扩容完成,新基线 | 观察,一般不处理 |
| 锯齿状反复 | 写入与过期回收交替 | 核对 TTL 分布 |
| 持续单调上升 | 数据或缓冲真在增长 | 按容量与泄漏方向排查 |
看到双表过渡就当成内存泄漏反复排查,是常见的无效动作;先看曲线是否收敛到新基线。
扩容密集期需要额外水位:预留不足时,rehash 的临时占用可能先把实例推到 maxmemory 触发淘汰。