Skip to content
返回运维与 SRE

容量余量

维持被测容量余量使流量突增不致饱和宕机。

为什么

跑 95% CPU 的服务距宕机一条病毒推文 — 无 20% 流量突增、重试风暴或加 5% 负载部署的余量。容量余量是当前利用率与服务退化点间的缓冲,维持它(关键资源通常 30-50% 余量)是你能做的最便宜可靠性投资。陷阱是余量感觉浪费钱 — "我们付不需要的服务器"— 但 30% 过配成本是一次饱和宕机损收入和客户信任成本的一小部分。跟踪余量并在低于 30% 时告警的团队在正常增长中抓容量问题,非在突增变宕机时。

何时使用

对每有状态资源(DB、缓存、队列)和每自动扩缩服务的基线。预期突增前(发布、营销、季节)审查。

如何做

1. 识别每资源饱和点
   - DB:连接池耗尽、CPU >80%、磁盘 IOPS 限
   - 缓存:驱逐率 >1%、内存 >90%
   - 队列:深度无界涨、消费者滞后增
   - 服务:p99 延迟在某 QPS 急升("膝")

2. 测当前利用率 vs 饱和点
   - headroom = (saturation_point - current_utilization) / saturation_point
   - 每资源仪表盘跟踪;余量 <30% 告警

3. 每资源类设余量目标
   - 有状态(DB、缓存):30-50% 余量(难快扩需缓冲)
   - 无状态自动扩:20% 余量(自动扩缩器处理突增,只需基线缓冲)
   - 单实例(无 HA):50%+ 余量(无故障转移需退化余量)

4. 对余量侵蚀告警,非仅绝对利用率
   - "DB CPU >70% 持续 1h" → 工单(余量 <30%,规划容量)
   - "DB CPU >85%" → page(余量 <15%,迫近饱和风险)
   - 跟踪趋势非快照 — 70% 每周升 1% 紧急

5. 从增长率 + 突增缓冲规划容量
   - current × (1 + weekly_growth) × (1 + spike_buffer) = N 周后需容量
   - 需要前订硬件/调大小,非告警触发时

示例

# 容量余量仪表盘(每资源)
# DB(Postgres):
db_cpu = 68%  # 饱和 85% → 余量 = (85-68)/85 = 20%  ⚠ <30%,工单
db_connections = 180/200  # 90% → 余量 = 10%  🔴 page
db_disk_iops = 12000/15000  # 80% → 余量 = 20%  ⚠

# 缓存(Redis):
cache_memory = 78%  # 驱逐 90% → 余量 = 13%  ⚠
cache_eviction_rate = 0.3%  # <1% 正常

# 告警规则:
- alert: DbHeadroomLow
  expr: (85 - avg(db_cpu_pct)) / 85 < 0.30  # 余量 <30%
  for: 1h
  labels: { severity: ticket, team: platform }
  annotations: { runbook: "https://rb/db-capacity-plan" }

# 容量规划(基于增长):
#   current_qps = 500,周增长 = 2%,突增缓冲 = 50%(黑五)
#   qps_8_周后 = 500 × 1.02^8 × 1.5 = 500 × 1.17 × 1.5 = 878
#   → 第 8 周需 878 QPS 容量;现在订升级

常见问题

  • ⚠跑 90%+ "省钱"— 省的是一次饱和宕机成本的一小部分;余量是你能买的最便宜保险。
  • ⚠对绝对利用率(CPU >80%)告警而非余量 — 100 连接池的 80% 没事,250 限 200 池的 80% 不行;跟踪余量。
  • ⚠无增长率跟踪 — 你到 70% 订需 4 周到的硬件,届时你 88% 饱和。
  • ⚠自动扩缩器藏基线余量问题 — 扩缩器不停加实例但 DB(不能自动扩缩)饱和;跟踪每资源非仅易的。

最佳实践

  • ✓有状态资源(DB、缓存)维持 30-50% 余量因不能快自动扩缩;自动扩缩无状态服务 20% 通常够。
  • ✓对余量(到饱和的边距)告警非绝对利用率 — 同百分比对不同池大小意味不同边距。
  • ✓跟踪增长率并需前 N 周订容量,计采购提前期 — 别告警触发时订。
  • ✓预期突增前(发布、黑五)预扩缩并压测确认余量;别依赖自动扩缩器在突增中救你。