容量推导与故障余量:十二台实例为何仍不够
三区各 4 台、单机 500 请求/秒、峰值 4,000——账面能力 6,000,看似充裕;失一区后恰好 4,000,一次 1.1 倍重试就过载。本页建立业务量到资源需求的完整换算,把缓存失效、重试放大、重建与冷启动作为联合场景决定余量。
容量推导的换算链
从业务量推导数据库 QPS 时应乘以每个业务动作的读写次数、缓存命中失效、重试和后台作业影响。对象存储容量还要加入副本、索引、日志、备份和保留期。线程或连接数取决于并发等待、持有时间与资源限制。把数据库连接池扩大到请求峰值会增加服务端切换和锁竞争,且不保证缩短排队时间。
N+1 或跨区容量规划需明确 N 的可持续安全能力、单故障后入口负载是否均匀、数据副本是否可写、重建期间资源是否够用。高可用余量不能仅由实例数决定。
完整案例:十二台实例为何仍不够
内容查询服务部署三可用区,每区 4 台。单实例在目标延迟下可持续处理 500 请求/秒,正常业务峰值 4,000 请求/秒,读占 90%,写占 10%,读请求正常命中缓存 95%。假设每个读未命中产生 2 次数据库查询,每个写产生 3 次写访问。单机 500 是题设安全能力,未在本资料中伪装成真实压测结果。
正常应用总能力为 6,000,单区失效后只有 8 台、4,000 请求/秒,正好贴着安全能力,没有冷启动、热点与恢复余量。若客户端重试使尝试放大到 1.1 倍,实际输入 4,400,已经超过单区故障后总能力。若希望故障后仍保留 20% 的规划余量,则目标可用能力需至少 4,400/0.8=5,500,即 11 台幸存实例;三等份部署要满足失一区仍至少 11 台,至少每区 6 台,共 18 台。80% 是本例选择,不能当普遍利用率定律。
数据库正常读负载为 4,000×90%×5%×2=360 次/秒,写负载 4,000×10%×3=1,200 次/秒。单区失效后缓存命中率降为 60%,若输入含重试为 4,400,数据库读放大为 4,400×90%×40%×2=3,168 次/秒,写约 1,320。应用节点够不等于数据库够,冷缓存使读查询接近正常的 8.8 倍,且读与写可能竞争相同 I/O 和锁。这类负载转移与"失去部分容量导致剩余副本过载"的风险见 Google SRE 级联故障;数字模型由本案例给出,不能直接套 Google 的资源利用率或故障规模作为自己的容量保证。
存储、连接和恢复也占余量
每天新增 20,000,000 条记录,每条业务数据 1KiB,保留 30 天。原始数据约 20,000,000×30×1,024=614.4GB,此处 GB 用十进制。若索引占原始的 50%,在线三份数据为 614.4×1.5×3=2,764.8GB。备份、binlog、快照、临时排序空间和存量更新另计,不能把三副本既放进倍数又再次相加。
数据库连接上限分配要按全部实例、后台任务与管理余量考虑。18 台每台池 50 个就是 900 个潜在连接,未必有 900 个并发查询的处理能力。建立连接数、活跃查询数、持锁事务数和等待队列的分别观测,限制长期空闲事务;把服务端最大连接数设置很高并不产生 CPU 或 IOPS。
副本恢复需要读旧数据、传输并重建索引。若在线负载已经用完所有读 I/O,重建会延长用户尾延迟;若完全不恢复,又会长期失去冗余。要给恢复任务设置速率,并算恢复完成期间再失一台的风险。容量计划不能把同一份 20% 余量同时承诺给故障接管、数据回填和积压清理三次。
过载控制的操作顺序
先判断核心不变量是否受威胁,停止不可安全重复的盲重试;按租户和业务类别限制新并发,暂停非必要回填;对推荐、统计等可选读取允许返回明确标注的陈旧值或少量结果;对余额、库存裁决等保持权威检查,不能返回伪成功。再对健康实例逐步引流,确认数据库等待和最老任务年龄回落,最后恢复后台作业。
熔断与限流职责不同:熔断减少坏依赖的无效调用,限流在总体需求超过资源时控制接纳,超时限制等待;三者都不能凭空增加容量。固定每秒额度也可能对大请求失效,需要结合成本单位和在途并发。SRE 处理过载强调请求成本差异与按客户保护,具体拒绝优先级应由本系统价值与义务决定。
故障时序可写为 t0 A 区失联,t5 流量转至 B/C,t6 冷缓存触发数据库读突增,t8 客户端重试放大,t10 B/C 延迟升高。若 t10 再重启所有实例,会同时丢掉更多缓存与在途上下文。正确动作要有观测和停止条件,而不是"一键重启试试"。切换脚本应预先读取幸存容量与保护配置,不能只按健康探针计数。
余量不可复用:接管、重建与积压追赶共用同一份 20%
故障余量算例给出"20% 规划余量 → 18 台",但评审常把这份余量同时承诺给三种工作:故障接管、数据重建、积压清理。三者共享同一批 CPU、连接与数据库容量,必须相加后再与余量比较,而不是每项单独"看起来够"。
沿用正文输入:三区各 4 台、单机 500、峰值 4,000、1.1 倍重试后 4,400,希望保留 20% 余量,目标能力 4,400/0.8=5,500,即 11 台幸存实例、每区 6 台共 18 台。18 台的总能力是 9,000/秒,故障后幸存 12 台、可服务 6,000/秒,相对 4,400 的输入余量是 1,600/秒(占幸存能力的 26.7%、占输入的 36.4%)。这份 1,600/秒要同时覆盖:故障接管后的流量再分配波动(假设 400/秒)、重建副本的读带宽折算(假设 500/秒)、积压追赶(假设 400/秒)。三项合计 1,300/秒,仍在 1,600 之内;但只要任一项翻倍——例如重建从 500 升到 1,200——合计变成 2,000/秒,已超余量 400/秒,18 台也不再达标。
数据库侧更早暴露:正常读 360/s、写 1,200/s,合计 1,560/s;故障后读 3,168/s、写 1,320/s,合计 4,488/s,已超数据库上限 3,500/s 约 988/s。此时再加重建的 500 与追赶的 400,合计 5,388/s,超出 1,888/s。不管应用加多少台,数据库都不能同时完成三件事——余量在应用层与数据库层不是同一份资源,必须分层计算。
执行 python3 labs/capacity_models.py reserve_reuse:输入上述五项。预期输出 fleet_survivor_capacity=6000、fleet_headroom=1600、workloads_sum=1300、workloads_rebuild1200=2000、db_total_fault=4488、db_deficit=988、db_with_background=5388。脚本只做加减,不模拟重建速率与锁竞争。
两种方案:A 扩容到余量能覆盖三件事同时发生(约 24 台以上并扩数据库),成本高但保留全部恢复能力;B 给重建与追赶限速,按优先级串行执行(先接管、再清理、最后重建),成本低但恢复窗口拉长。本例选 B 并写明"最坏情况下三者不可并行"这一承诺,而不是把 20% 余量在文档里重复承诺三次。
两方案比较及架构师变式
方案 A 预置 18 台并保持缓存温度,故障后较快接管;成本较高且仍须验证数据库、跨区网络和热键。方案 B 保持 12 台,失区后对非关键 30% 流量限流并按优先级接纳,允许短期牺牲部分可用性以防全站级联。若这 30% 不能从核心业务中分离,B 不满足目标;若业务接受活动页降级而结算保持,B 可能更经济。
自动扩容并非等价于预置容量。假设检测、创建、预热分别要 30、90、60 秒,需 180 秒才可增加能力;其间每秒过载 400,就可能新增 72,000 个工作。若交互 deadline 只有 300ms,这些请求不能靠三分钟后扩容救回。异步任务能缓冲,但仍需要有界磁盘、明确完成目标与拒绝条件。
架构师变化条件为故障时另有每秒 500 查询用于重建,数据库安全上限 3,500 次总访问/秒。原故障模型已需约 4,488 次读写访问,恢复工作只会加重,必须先调整缓存回源、写入接纳或数据库能力。不能单独让应用扩容实验通过后宣称单区容灾达标。
可运行模型与交付物
运行 完整实验脚本:
python3 labs/capacity_models.py failure预期核对:正常读 360/写 1,200,故障后重试输入 4,400 下读 3,168/写 1,320,按 20% 余量需 18 台,model=zone-failure-fluid-not-drill。再在纸面把命中率改为 0%,算回源上界;把实例负载分配改为一台承担 20%,验证平均能力不能保护单个热点。本轮该公开脚本及断言已运行;真实区域故障演练未运行。
产物为联合故障容量表、访问放大表、存储口径、实例与连接池预算以及过载 Runbook。实际发布前需要真实负载曲线与失区演练;本页模型没有执行区域故障,也没有测得 500 QPS 单机能力。
闭卷验收
本页 8 道闭卷题收进了下方自测面板:先回忆,再展开参考答案与评分点,最后给三档自评。