装载因子与扩容是什么
Redis 的键空间是一个字典(哈希表),装载因子就是「已用元素数 ÷ 桶数量」。装载因子超过约 1 时字典会扩容:新桶数取不小于元素数两倍的最小 2 的幂,然后通过渐进式 rehash 把旧表逐个桶搬到新表。若此时正在做 RDB 保存或 AOF 重写,阈值会放宽到约 5,避免 fork 期间内存翻倍叠加写时复制。
基本信息
| 常规扩容阈值 | 装载因子约 1 |
|---|---|
| 保存/重写期间 | 放宽到约 5 才强制扩容 |
| 扩容幅度 | 按元素数翻倍并向上取 2 的幂 |
| 缩容阈值 | 装载因子低于约 10% 时由定时任务触发 |
| 迁移方式 | 渐进式 rehash,期间新旧两张表共存 |
| 观察手段 | DBSIZE 配合 INFO memory |
典型使用场景
- 预判内存台阶:知道扩容是按倍数的,容量规划就不会用线性模型
- 解释内存涨而键数没涨:rehash 期间新旧表共存,内存会短时抬高
- 避免水位边缘批量写入:扩容叠加 rehash 时最容易被淘汰规则砍数据
- 评估键设计:键多值小时桶指针开销占比升高,用 hash 分桶可以压缩
- 观察删除后的归还:大量删除不会立刻降内存,缩容是延后且渐进的
最小示例
最小示例
redis-cli DBSIZE # 当前键数量
redis-cli INFO memory | grep used_memory_human # 当前已用内存
redis-cli INFO memory | grep used_memory_peak_human # 峰值,能看到扩容带来的台阶
redis-cli INFO stats | grep -E 'evicted_keys|expired_keys' # 是否发生过淘汰
redis-cli --bigkeys # 抽样看键的分布形态扩容相关现象
| 现象 | 原因 | 应对 |
|---|---|---|
| 键数翻倍时内存跳台阶 | 桶表按 2 的幂扩容 | 容量按台阶估算,不要用线性外推 |
| 内存短时接近原来的两倍 | rehash 期间新旧两张表共存 | 避开在水位边缘做大批量写入 |
| 大量删除后内存不下降 | 缩容阈值低且由定时任务执行 | 看趋势即可,短期不降属正常 |
| 大批量导入时突然触发淘汰 | 扩容叠加批量写入推高内存 | 分批导入并预留余量 |
桶本身就是开销:每个桶一个指针,元素很少、键极多时,桶表占用可以与数据本身同量级,这也是小对象多的场景更适合 hash 分桶的原因。
保存期间把阈值放宽到 5,是为了让扩容尽量避开 fork 窗口;所以持久化期间内存更容易陡增,这段窗口内的占用要单独留余量。