首页/数据/Redis 进阶速查/渐进式 rehash 与双表过渡
内存与管理99 条

渐进式 rehash 与双表过渡

字典扩容时保留新旧两张哈希表渐进迁移,期间内存短时接近翻倍、访问走两表;大字典扩容是内存尖峰的常见来源。

Redis 进阶速查数据更新于 2026-10-13

渐进式 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 触发淘汰。

易错点

  • 把 rehash 双表过渡当内存泄漏,反复做无意义的排查
  • 容量规划没有为扩容窗口留水位,尖峰直接触发淘汰甚至 OOM
  • 把 fork 期间推迟扩容导致的内存上涨归因到业务写入
  • 只看单次采样值判断内存正常,错过缓慢上涨的趋势
  • 对超大 hash 不做拆分,单次扩容幅度过大造成明显抖动

数据来源与参考

  • Redis 官方文档:字典 rehash 实现说明
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌