系统日活从 100 涨到 10 万,架构要变什么?
谁在问:三面 / 架构向;常与成本追问成对出现,考的是你有没有在真实规模上待过
口语化问法
- 这套东西现在只有一百个人在用,涨到十万日活,哪儿会先崩?
- 用户量翻一千倍,你的架构要改什么?
- 大促当天流量再翻五倍,你怎么扛?
考察意图
这道题的第一个陷阱在题面里:「日活」不是容量单位。日活 10 万可能意味着峰值并发 50,也可能意味着 5000,取决于使用形态。上来就开始扩容的人,第一步就错了。
其余三层:
- 你知不知道各层的拐点不同。检索侧、生成侧、数据侧在完全不同的量级上出问题,一起扩是浪费。
- 你会不会做容量规划。峰值吞吐是宣传数字,真正能用于规划的是有效吞吐。
- 你知不知道一千倍不是线性放大。有些东西会变好(缓存命中率),有些会变差(长尾变长、评测集失效),有些会直接失效(人工兜底)。
参考答案
60 分答案(及格线)
先做水平扩展,检索服务和应用服务加机器、加负载均衡;向量库要考虑分片;模型调用侧要加限流和排队,避免打爆上游;再加缓存降低重复请求。监控要跟上,看各层的延迟和错误率。数据库读写分离,热点数据加 Redis。
这是通用的 Web 扩容答案,及格但不切题。它没有回答任何和大模型应用相关的特殊性——生成侧的容量约束、长上下文对并发的影响、缓存结构的变化、以及兜底策略的失效。
90 分答案(有生产经验的回答)
① 先澄清:涨的到底是什么。 日活 10 万要先换算成峰值并发和每秒请求数——同样是 10 万日活,一天用一次的工具和坐席全天在线的客服,并发差两个数量级。还要问:长上下文请求的占比是多少(这直接决定生成侧的容量),以及数据量是不是同步涨了(用户涨不一定文档涨,两者的扩容路径完全不同)。
② 回到基线:先找当前架构的第一个拐点在哪。 不要三层一起扩。做法是压测,看哪一层先崩。经验上顺序通常是:生成侧 → 检索侧 → 数据侧,因为生成侧的单位成本和资源占用远高于其他两层。
③ 分层说变什么、代价是什么:
- 生成侧(最先出问题的一层)。如果走 API,主要工作是限流、排队、优雅降级和多供应商冗余;如果自建,核心约束是显存:KV Cache 吃掉的显存决定了能同时挂多少条会话,容量限并发、带宽限单步。这里有一个必须说清的效应:上下文越长,并发掉得越快——同一张卡在 8K 上下文下能挂几十条并发,到 128K 可能只剩个位数。所以「支持超长上下文」在规模化之后是一个容量决策,不是一个功能开关。
- 容量规划只能用有效吞吐。峰值吞吐是「不管延迟多难看,一秒能吐多少 token」,而真实业务有延迟约束,满足延迟要求的那部分吞吐才能用于规划。用峰值吞吐做容量规划,上线当天就会发现算少了一半。
- 检索侧:向量索引到一定规模要分片,且召回质量会随库变大而下降——同样的 top-k 在百万级库里的噪声比十万级大得多,所以扩容的同时通常要提高召回数并加强重排。代价:延迟和成本都上升。还要注意增量更新的压力:数据量涨了之后,重建索引从「凌晨跑一次」变成不可行,必须做真正的增量。
- 数据侧:更新频率、一致性、以及权限判定的 QPS(toB 场景里这一项经常被漏,每次检索都要查一遍权限)。
- 缓存结构会变好:用户涨一千倍之后,问题分布会更集中,精确缓存和前缀缓存的命中率通常显著上升——这是规模带来的红利,应该主动去吃。但语义缓存的风险同时放大,因为误命中的绝对次数随请求量线性增长。
- 长尾会变长:100 个用户时你见过的问题类型是有限的,10 万用户会把长尾拉得很长。这意味着评测集会失效——原来的一百条评测题不再代表线上分布,必须按新的真实分布重采。这条最容易被漏,但它是「上线后效果变差」的常见原因之一。
- 兜底策略会直接失效:100 日活时「不确定就转人工」完全可行,10 万日活时人工兜底会被淹没。所以扩容不只是扩机器,是要重新设计兜底——把一部分兜底从人工换成自助(引导到帮助中心、给相似问答、给结构化表单)。
④ 怎么验证扩对了:压测要用真实分布的流量回放而不是均匀请求,因为长上下文请求的资源占用完全不同;监控要分桶看(按请求类型、按上下文长度分桶),总均值会掩盖问题;同时要盯有效吞吐和排队时长,而不只是 QPS 和成功率。
⑤ 什么时候该做下一步:出现「峰值时排队时长超过用户耐心」→ 扩容或降级;出现「长尾问题占比持续上升且转人工被打满」→ 该扩知识覆盖和自助兜底,不是扩机器;出现「同一类请求每天几万次且稳定」→ 才考虑蒸馏小模型或专用路由。退路:任何一次扩容后效果指标下降,先回滚再排查——规模问题最容易和质量问题混在一起,不隔离就查不清。
追问链
你会先扩哪一层?怎么判断?
期望不猜,压测:① 真实分布的流量回放逐层加压,看谁先崩;② 经验顺序是生成侧最先,但必须验证不能假设 —— 库特别大或权限判定特别重时顺序会变;③ 判据不是「谁的 CPU 先满」,是谁先突破延迟约束;④ 扩之前先找便宜办法:缓存命中率、重复请求、有没有一类请求本来就不该走完整链路信号说得出「用真实分布回放而不是均匀压测」→ 压过真实系统;直接给扩容顺序不谈验证 → 背的经验为什么长上下文场景并发掉得那么快?
期望KV Cache 随上下文线性吃显存,而显存固定。① 单条占用看长度、层数、KV 头数(不是注意力头数,分组查询注意力下差很多)、精度;② 总显存 ÷ 单条占用 = 并发上限,容量限并发;③ 每步解码重读 KV Cache,带宽限单步。同卡 8K 挂几十条,128K 只剩个位数信号用 KV 头数而不是注意力头数算 → 学过真东西;点出「memory-bound 是关于 batch size 的陈述」→ 理解到位峰值怎么算容量?按供应商标称的吞吐吗?
期望不能。① 标称峰值在无延迟约束下测得,真实业务有首字与逐字延迟约束,只有满足延迟约束的那部分吞吐可用于规划;② 按有效吞吐算并按请求类型分桶,长上下文与短请求不能混一个数;③ 留余量给排队:到达不均匀,按平均值规划会在峰值全线排队;④ 自建再算预热、模型加载、故障时的容量重分布信号明确说「峰值吞吐不能用于容量规划」→ 做过容量规划;拿标称数字乘个系数 → 没上过量用户涨一千倍,缓存命中率会怎么变?
期望通常变好,但要分层看:① 精确与前缀缓存命中率上升:用户越多问题分布越集中,是规模红利 —— 把系统提示和工具定义固定死去吃它;② 语义缓存绝对风险同步放大,误命中次数随请求量线性涨,责任在你;③ 反向效应是长尾变长,尾部命中率反更低,总命中率上升会掩盖尾部变差 —— 必须分桶看信号说得出「总命中率上升可能掩盖尾部变差」→ 看过真实的分桶数据;只说「缓存会更有用」→ 答对一半大促当天流量再翻五倍,上游还限流了,你怎么降级?
期望按从不影响正确性到影响功能排:① 削非关键路径(解释性输出、相关推荐、可选二次校验,安全类保留)→ ② 降召回数、重排数、effort档位、最大轮次 → ③ 走缓存与预置答案(权限场景必须分桶)→ ④ 按用户与请求分级排队,等待可见 → ⑤ 减功能:关长尾入口、不可逆操作转人工。上游专项:多供应商冗余、快速失败、退避抖动、幂等;恢复条件事先约定、能一键回滚信号给得出「从不影响正确性到影响功能」的降级链并提退避抖动与幂等 → 真值过大促;只说「加机器 + 限流」→ 没有优先级概念
评分要点
- 先把日活换算成峰值并发,并问长上下文请求占比
- 不三层齐扩,压测找第一个拐点
- 生成侧讲清 KV Cache 三层账(容量限并发、带宽限单步)
- 容量规划用有效吞吐而非峰值吞吐,且按请求类型分桶
- 检索侧知道库变大召回质量下降,要提召回数并加强重排
- 知道规模带来缓存红利,但语义缓存风险同步放大
- 知道长尾变长会让评测集失效,必须按新分布重采
- 知道人工兜底会在规模化后失效,兜底策略要重新设计
- 降级给出有优先级的链条,含退避抖动与幂等