大促前备机器,备多了浪费成本,备少了系统崩。这句话谁都同意,但真到决策时,备多少这个问题几乎总是变成拍脑袋。研发拍一个数,运维拍一个数,老板觉得贵再砍一刀,最后落到一个谁都没底气的数字上。容量评估这套方法存在的意义,就是把拍脑袋换成可推导的数据,让备机器这件事有依据、能复盘、能迭代。
容量评估的完整链条是四步,预估大促会来多少流量,压测得出单机能扛多少,用总流量除以单机容量推出机器数,再把全链路各层的资源分别核算一遍。听起来朴素,每一步里都藏着坑。最大的坑是人们只盯着应用层机器数,把缓存、数据库、MQ、带宽这些依赖层全忽略掉,结果应用扩容扩得飞快,瓶颈却卡在 DB 连接打满或者带宽跑满上。
流量预估,基于历史而不是直觉
预估大促峰值 QPS,唯一可靠的依据是历史数据加增长系数。去年同期那场大促的峰值是多少,今年用户量和 GMV 同比增长了多少,这次活动力度比去年更猛还是更保守,综合这几个因素推一个数出来。
举个具体的算法。去年双 11 峰值是 5 万 QPS,今年用户增长 30%、活动力度和去年持平,那预估峰值大概 6.5 万 QPS。这是基础值,再叠一个 20% 的突发余量,按 8 万 QPS 来做后续的资源规划。这个余量不是浪费,是给预估的误差留缓冲,流量预估永远有不确定性,宁可备了没用,不能要用没有。
另一种思路是从 DAU 倒推。日活用户数乘以大促当天的活跃系数,再乘以人均操作次数,得到一天的总请求量,再按大促流量集中在几个小时的峰值特征折算成峰值 QPS。这种算法适合没有历史大促数据可参考的新业务,但系数都要拍,误差比直接用历史峰值法大。
单机容量,只能压测不能估算
图:单机容量压测流程——逐步加压找到响应时间拐点,取拐点 70%~80% 作为安全容量
单机能扛多少 QPS,这一步没有任何捷径,必须压测,不能靠经验估算。
为什么不能估算。单机容量取决于太多变量,代码质量、依赖的外部服务性能、JVM 的 GC 表现、硬件配置,这些加在一起决定了真实容量,靠 8 核 16G 理论能扛 5000 QPS 这种话去备机器,实际跑起来可能 2000 就拐了。我见过一个团队就这么备的,结果上线发现慢 SQL 把数据库连接全占住,应用层 2000 QPS 就开始响应剧增,备的机器差一倍,大促当天手忙脚乱扩容。
压测找的是拐点。给单机逐步加压,响应时间一开始是平的,到某个点开始急剧上升,CPU 也接近满载,这个点就是拐点。安全容量取拐点的七成到八成,留出余量,因为生产环境的负载比压测复杂,依赖更多、流量更不均匀。比如压测到 2000 QPS 开始拐,安全容量按 1500 算。
取拐点而不是取峰值,是因为拐点之后系统虽然还能跑,但已经处于性能急剧恶化的边缘,任何一点突发流量就会拖垮整个链路。留七成余量,就是为了让系统在大促当天有处理突发的空间。
任何脱离压测的单机容量数字都是猜的。同样规格的机器,代码写得好能跑 3000,写得烂 1000 就拐,这个差距压测才能暴露。备机器之前先把目标接口在准生产环境压一遍,拿到真实的单机安全容量,再去做后续推导。跳过这步直接估算,等于把整个容量规划建立在沙子上。
机器数推导,公式加上冗余
图:机器数推导——总 QPS 除以单机容量得基础数,再叠加容灾、突发、灰度三类冗余
有了总目标 QPS 和单机安全容量,机器数就是一个除法,总 QPS 除以单机容量。8 万 QPS 除以单机 1500,基础机器数大约 54 台。
这个基础数还要乘上冗余系数才安全。冗余要覆盖几种情况。单机房容灾,某个机房整体故障,其他机房要能接住全量流量,通常要加三成到五成。突发流量,预估不准的余量,再加两成。灰度发布期间,一部分实例在下线更新,剩下的要扛住,再加一成左右。综合下来,54 台乘以大约 1.5 的冗余系数,最终备 80 台上下。
冗余系数不是越多越好。机器备太多,固定成本吃不消,而且大促过后这些机器闲置,资源利用率很低。冗余要基于真实的风险评估,机房是不是多活、发布是不是能平滑、预估的置信度有多高,这些都影响冗余给多少。我倾向于把容灾冗余算足,突发冗余适度,因为机房故障是低概率高后果,宁可多备一点。
全链路各层都得核算,木桶效应
图:全链路分层容量核算——每层单独核算,越往下扩容越难,余量留得越足
容量评估最容易犯的错,是只算应用层机器数,把依赖层全忽略。但大促翻车往往不在应用层。应用扩容容易,点几下就多出几十台,DB 和缓存扩容却是天大的工程。真正的容量瓶颈,几乎都卡在那些难扩容的依赖层上。
每一层都要单独算。网关层算入口 QPS 和带宽。应用层算业务 QPS 对应的 CPU 和内存。缓存层算缓存 QPS 和内存容量,这里的关键是命中率,命中率够高缓存才扛得住,命中率掉一点穿透到 DB 的流量就翻倍涨。数据库层算读写 QPS、连接数、存储容量,DB 是最难扩容的,要按一年后的数据量来前瞻规划,不够就得提前分库分表。MQ 算消息吞吐量和堆积容忍。带宽算入口和出口的峰值。
缓存容量要这么算。先预估大促涉及的热点数据量,比如 1000 万个 SKU 的详情。估算单条数据大小,比如 2KB。总内存等于数据量乘单条大小,1000 万乘 2KB 是 20GB。再加主从副本和内存碎片余量,按 30% 算,规划 60GB 左右的集群。再除以单分片容量确定 Redis 分片数。这套算法把缓存从拍脑袋变成可推导。
数据库容量更得前瞻。DB 是整套系统里扩容代价最大的组件,分库分表是单行道,一旦分了就回不去。所以 DB 的容量规划要看得最远,存储按一年后的数据增量算,连接数按应用实例数乘单实例连接池算清楚不能超过 DB 的最大连接,读写 QPS 不够就要提前规划加从库或者分库分表,不要等到大促前一个月才动。
我见过的大促容量事故,应用层机器不够的反倒少,因为应用扩容快。真正翻车的全是 DB 连接打满、缓存容量不足撑不住命中率、出口带宽被图片和视频跑满这几类。应用层扩容再快也救不了这些底层瓶颈。所以容量评估从应用层往下每一层都要算,并且越往下越要留足余量,因为越往下扩容越难、越慢、风险越大。
带宽是隐蔽的瓶颈
带宽这块容易低估。出口带宽尤其危险,用户下载图片、视频、商品详情把出口带宽占满,所有服务都会变慢,因为服务间调用的内网流量也走同一条管道。
静态资源一定要走 CDN,把图片、视频、JS、CSS 这些从源站带宽里剥离出去,源站只承担 API 响应。API 响应能压缩的压缩,gzip 或者 brotli,JSON 体积能砍掉七成。监控带宽使用率,到 70% 就该告警,因为带宽是运营商那头的物理资源,临时扩容周期长,等满了再救已经晚了。
内网带宽也别忽略,服务间 RPC 调用、MQ 消息流转、缓存读写,这些都在吃内网带宽。大促流量下内网流量会成倍增长,尤其是那种一次 RPC 返回大对象的接口,流量放大效应很明显。
用全链路压测验证
容量评估做完,最后一步是用全链路压测验证。预估只是假设,压测才是事实。
按预估配好的资源,用真实流量模型把链路压到目标 QPS,看每一层的指标是不是都在安全水位。应用层 CPU、响应时间,缓存层命中率、内存,DB 层连接数、慢查询,带宽使用率,任何一层触红线都说明预估偏了,要么那层扩容,要么优化代码降低那层的压力,然后重新压测验证。
这个验证,反馈,再验证的循环是容量评估靠谱的保证。预估是建立在一系列假设上的,假设会错,压测把错误暴露出来。我每次大促前的容量评估至少跑两到三轮压测,第一轮通常会暴露几个没算到的瓶颈,修完再压,直到全链路稳定扛住目标 QPS 持续几个小时,才算容量规划成立。容量评估不是一次性的动作,是每次大促前的常态化功课,每一轮的真实数据都让下一轮的预估更准。








