4. 容量评估方法

Redis 容量评估的核心目标,是回答一个具体问题:这个实例需要预留多少内存,才能在业务峰值下稳定运行且不触发淘汰或 OOM? 很多团队习惯用“当前数据量 × 2”拍脑袋估算,结果要么浪费资源,要么在促销、大促时被写满。更可靠的做法是把内存需求拆成可量化的几个因子:业务 QPS、平均 KV 大小、过期策略、峰值倍率,再叠加 Redis 自身的运行时开销。

一、容量公式的构成

一个可落地的估算模型可以写成:

实例内存需求 ≈ 稳态数据内存 × 峰值倍率 + 运行时开销 + 安全余量
稳态数据内存 ≈ 键数量 × (平均 Key 大小 + 平均 Value 大小 + 单键元数据开销)
键数量 ≈ 写入 QPS × 平均存活时长 × 冗余系数

这里每个因子都有明确的业务含义。QPS 决定写入速率,平均存活时长由过期策略决定,两者相乘得到稳态键数量;平均 KV 大小决定单键占用;峰值倍率覆盖流量突增;运行时开销包括复制缓冲区、客户端缓冲区、AOF/RDB 重写时的额外内存等。

二、QPS 与过期策略如何决定键数量

如果业务是“写入后 30 分钟过期”的会话缓存,写入 QPS 为 2000,那么稳态键数量约为 2000 × 1800 秒 = 360 万。若过期时间是 2 小时,则键数量会膨胀到 1440 万。这说明过期策略直接决定内存规模,而不是 QPS 单独决定。

过期策略还要区分两种模式:

  • TTL 自动过期:键在到期后被惰性删除或定期删除,稳态键数量趋近于“写入速率 × TTL”。
  • 显式删除或覆盖写:键数量由业务逻辑控制,可能长期累积,需要单独评估增长曲线。

对于没有 TTL 的集合类数据(如 Hash、ZSet),键数量可能持续增长,此时必须结合业务增长率和历史数据做趋势外推,而不能只依赖 QPS。

三、平均 KV 大小与单键开销

平均 KV 大小不能只看 Value 的字节数。Redis 中每个键都有 dictEntry、redisObject、SDS 头等元数据开销。以 64 位系统为例,一个简单的 String 键值对,即使 Key 只有 10 字节、Value 只有 20 字节,实际占用也可能达到 80~120 字节。因此估算时应使用“有效载荷 + 元数据开销”的口径。

假设某业务平均 Key 为 32 字节,平均 Value 为 256 字节,单键元数据开销按 64 字节估算,则单键约 352 字节。若稳态键数量为 500 万,则数据内存约为 500 万 × 352 B ≈ 1.76 GB。这个数字还没有考虑峰值倍率和运行时开销。

四、峰值倍率与安全余量

峰值倍率是容量评估中最容易被低估的因子。它至少包含三层含义:

  • 流量峰值倍率:大促或活动期间 QPS 可能是日常的 3~10 倍,导致写入速率和键数量同步上升。
  • 数据膨胀倍率:某些业务在峰值期间会写入更大的 Value,或产生更多临时键。
  • 运行时开销倍率:主从复制、AOF 重写、RDB 快照期间,内存可能额外增加 30%~100%。

工程上通常建议:实例最大内存 = 稳态数据内存 × 峰值倍率 × 1.3~1.5。其中 1.3~1.5 是安全余量,用于覆盖碎片率和运行时缓冲。若业务对可用性要求极高,余量应取上限。

五、一个完整的估算示例

假设某电商购物车服务:日常写入 QPS 为 800,平均 Key 40 字节,平均 Value 600 字节,TTL 为 7 天,大促峰值倍率为 5,单键元数据开销按 80 字节估算。

稳态键数量 = 800 × 7 × 86400 ≈ 4.84 亿
单键占用 = 40 + 600 + 80 = 720 B
稳态数据内存 = 4.84 亿 × 720 B ≈ 348 GB
峰值数据内存 = 348 GB × 5 = 1740 GB
实例内存需求 = 1740 GB × 1.4 ≈ 2436 GB

这个结果说明:如果 TTL 长达 7 天,即使 QPS 只有 800,内存需求也会达到 TB 级。此时应考虑缩短 TTL、分片部署,或改用更紧凑的数据结构。反过来,如果 TTL 缩短到 1 天,稳态键数量降到约 6900 万,内存需求会大幅下降。

估算时建议同时计算“日常内存”和“峰值内存”两个值。日常内存用于容量规划,峰值内存用于设置 maxmemory 和告警阈值。maxmemory 应略低于实例物理内存,为复制缓冲区和系统预留空间。

六、参数关系可视化

下图展示了各因子之间的传导关系:QPS 与 TTL 共同决定键数量,键数量与平均 KV 大小决定数据内存,再经过峰值倍率和安全余量得到最终实例内存需求。

Redis 内存需求估算因子传导关系 业务 QPS 写入速率(次/秒) 过期策略 / TTL 平均存活时长 平均 KV 大小 Key + Value + 元数据 稳态键数量 QPS × TTL × 冗余系数 稳态数据内存 键数量 × 单键占用 峰值倍率 流量 / 数据 / 运行时 实例内存需求 数据内存 × 峰值倍率 × 安全余量 安全余量 1.3~1.5 碎片率 + 复制缓冲 + 系统预留 注:单键占用 = Key 大小 + Value 大小 + 元数据开销;元数据开销通常按 50~100 字节估算

七、估算后的校验与调整

公式给出的是理论值,落地前还需要用真实数据校验。可以在测试环境写入一批样本键,用 MEMORY USAGE key 查看单键实际占用,再乘以预估键数量。也可以用 INFO memory 观察 used_memory 与 used_memory_rss 的差异,判断碎片率是否在合理范围。

如果估算结果远超单实例承载能力,通常有三条调整路径:缩短 TTL 以降低稳态键数量;拆分实例或使用 Cluster 分片;优化数据结构,例如用 Hash 替代多个 String 键,用 ZSet 替代多个 List。容量评估不是一次性的计算,而应随着业务 QPS、TTL 和 Value 大小的变化定期复算,并在监控中设置内存使用率告警,确保峰值到来前有足够的扩容窗口。