图 1:本文封面,点明题目与五层架构主线。
先说明属性:这是一篇经典题解析,题目出自本地历史面试资料(见文末来源说明),与任何公司的当前招聘无关。开放式设计题没有标准答案,面试官真正想看的是:面对「高并发」三个字,你是有一套展开框架,还是只会背组件名词。
想象面试现场,面试官问:「如果让你设计一个支撑高并发的系统,你会从哪几个方面考虑?」
第一步,审题:先把「高并发」翻译成数字。
不要急着答方案。高并发是形容词,设计需要数字:预期的 QPS 是多少、峰值是均值的几倍、读写比例如何、延迟目标多少、数据量多大。一个每秒一千次查询的只读服务和一个每秒一万次写入的订单系统,长相完全不同。开口先要约束条件,这个动作本身就是加分项。
第二步,基础回答:五层框架。
拿到数字后,按五层展开,每层回答一个问题。
接入层:放多少流量进来?负载均衡把流量摊到多个实例;限流把超出承受能力的请求在入口就快速拒绝掉;降级预案提前排好优先级,紧张时刻先保核心链路。
应用层:应用能不能横向加机器?核心是让服务无状态——会话、文件这类状态挪到外部的缓存与存储里,任何一台实例挂了请求都能落到别的实例上。无状态是水平扩展的前提,也是这一层唯一重要的设计决定。
缓存层:多少读流量根本不该到数据库?本地缓存加分布式缓存,让绝大多数读请求在到达数据层之前就被挡掉。这一层引入了一致性问题,要用过期时间与更新策略管住它。
异步层:哪些事根本不用同步做?写入侧的瞬时尖峰用消息队列削平——先把请求接下来排队,后端按自己的能力匀速消费;发通知、写日志、更新统计这类操作挪到请求链路之外,主链路只保留非做不可的工作。
数据层:数据库本身扛不扛得住?读流量大就读写分离,把读分给副本;单表太大再考虑分库分表。这是最后一道防线,手段最重、改动最贵,留到最后用。
图 2:五层设防与取舍原则——请求挡在越上层,成本越低。
第三步,取舍顺序:手段不是越多越好。
框架之外更重要的是顺序。一般原则是:能用缓存挡住的流量,别让它到数据库;能异步做的事情,别让它占主链路;限流和降级是兜底保险,平时就要配好演练好;扩容解决的是整体水位,解决不了瞬时尖峰——扩容是分钟级动作,尖峰是秒级的。
关于「过载时怎么办」,Google 的 SRE 手册有一章专门讨论,几个观点值得直接引用:其一,降级响应是正常手段——过载时返回「够用但不完美」的结果(比如只搜一小部分候选集),比硬扛到崩溃好;其二,限流应该按客户配额做,让超额的那部分客户失败,而不是全体一起失败;其三,可以按请求的关键程度分级,系统过载时先拒绝低优先级的请求;其四,客户端发现大量被拒绝后应自我节流,并且重试要设预算,防止「越失败越重试」把后端压垮。这些原则的共同底色是:系统的目标不是满足所有请求,而是在任何负载下都不崩溃。
第四步,可能的追问。
「怎么知道瓶颈在哪一层?」压测加监控:逐层打压力,看哪一层的延迟先抬头。「缓存和数据库先上哪个?」看读写比,读流量占比高先上缓存。「无状态化做不到怎么办?」把状态集中到外部存储是标准解,实在不行用一致性哈希做会话亲和,并接受扩展性受损。
工程应用与 AI 关联。
大模型推理服务把这道题放大了:单次调用延迟高、成本贵,排队、异步、限流、分层缓存每一种手段都直接决定可用性和单位成本。按客户配额限流、对批处理流量降级、给推理结果做缓存,都是从这套框架直接平移过去的。
易错点清单。
一,开口就答「加机器」——不量化目标、不拆层,等于没有方法论。二,把五层手段全部罗列一遍却讲不出取舍顺序。三,忽略降级与限流这些「失败时的设计」,只设计晴天场景。四,把扩容当万能药,忽略它对秒级尖峰无能为力。
回到面试现场,建议的答题节奏:先要数字,再给五层框架,然后讲取舍顺序,最后补过载保护原则。这个结构展示的是设计方法论,而不是组件清单的背诵。
如果让你设计一个 AI 推理服务的过载保护,配额、降级、客户端节流这三样,你会优先上哪一个?说说你的理由。
参考资料
- Handling Overload(Google SRE Book 第 21 章:降级响应、按客户配额限流、请求关键程度分级、客户端自适应节流、重试预算、过载时快速拒绝而非排队堆积) — https://sre.google/sre-book/handling-overload/