主题
系统设计题
本篇定位
覆盖容量评估方法、高可用设计原则、监控日志系统设计,以及一套可直接口述的完整设计范例。
高频面试题
Q1:怎么做容量评估?QPS、带宽、连接数、磁盘怎么算?
我的答案:
系统设计第一句话永远是"先问规模",我会主动要几个数:日活用户多少、峰值 QPS 多少、数据存多久。然后我会自己把账算给面试官看,这是加分项。
QPS:假设日活 100 万,平均每人每天访问 20 个接口,一天总请求就是 2000 万。按二八定律,80% 流量集中在 20% 高峰时段(约 4 小时),那平均 QPS ≈ 2000万 × 0.8 / (4×3600) ≈ 1100。峰值一般再乘 2~3 倍,按 3000 QPS 去设计。
带宽:假设每个响应平均 5KB,3000 QPS × 5KB ≈ 15MB/s ≈ 120Mbps,对外带宽按峰值留余量买 200Mbps,静态图片扔 CDN 回源,源站带宽就省下来了。
连接数:每台应用服务器能扛的并发连接取决于文件句柄和线程池。假设单台能稳定扛 500 QPS,3000 QPS 就需要至少 6 台,再留 1~2 台冗余做故障切换,总共 8 台。
磁盘增长:假设每条业务日志 1KB、每天写 500 万条,一天就是 5GB;数据库按每天新增 100 万行、每行 1KB 算约 1GB/天。按保留 1 年粗算,再乘 2~3 倍冗余,规划存储。
算完我会说:这些数都是粗估,真实容量靠压测和线上观测校准,但面试时能这样一步步算,就证明我有"用数字说话"的习惯,而不是上来就堆组件。
Q2:高可用设计有哪些核心原则?
我的答案:
高可用的目标是 SLA,比如要做到 99.95%,一年故障时间不能超过 4 小时。我用五条原则搭。
第一消除单点:任何组件都不能只有一份,一台挂了整个系统就得活着。应用多实例、数据库主从、SLB 后面挂多台。
第二无状态:应用服务器本身不存会话和文件,会话丢 Redis、文件放 OSS,这样任意一台挂了流量转给别的台无感,也能随便水平加机器。
第三负载均衡 + 健康检查:SLB 做分发,自动摘除不健康的后端实例。
第四故障自动切换:数据库主从复制 + 自动 failover,Redis 哨兵/集群,跨可用区部署,一个 AZ 挂了另一个顶。
第五备份 3-2-1:关键数据三份副本、两种介质、一份异地,定期做恢复演练——备份能不能用,得真恢复一次才算数。
还要配弹性伸缩扛突发流量,加上限流、熔断、降级兜底。我会强调:高可用不是堆机器,是每一层都问一句"这层挂了会怎样",答案不能是"全站崩"。
Q3:完整设计一个高可用 Web 架构(口述范例)
我的答案:
我以"一个面向 100 万日活的电商类 Web 服务"为例,从用户请求一路往后讲,这套可以直接脱稿说。
"假设我们要做一个高可用的 Web 业务,规模刚才算过约 3000 峰值 QPS。用户请求进来,第一步先到 DNS,解析到 CDN——静态图片、JS、CSS 全放 CDN 和对象存储 OSS,不回源,这样源站压力小一大半。动态请求回源到 SLB/CLB,SLB 后面挂 8 台无状态应用服务器,跨两个可用区部署,健康检查自动摘挂掉的实例。
应用层做成无状态:登录会话放 Redis 集群,Redis 做主从+哨兵保证自己也高可用。读多写少的热点数据(比如商品详情)先查 Redis,miss 才打数据库。
数据层:MySQL 用 RDS 主从,主库写、从库读,自动故障切换;大促前加只读实例分摊读压力。再往后是消息队列 Kafka,下单这种慢操作异步化,把用户请求先接住再慢慢处理,挡峰值。
整个系统配 Prometheus + Grafana 监控,告警接到 Alertmanager;变更走灰度和自动回滚;跨可用区容灾,关键数据做 3-2-1 备份。"
收尾我会主动说权衡:"这套架构的代价是组件多、运维复杂。如果业务早期没这么大,我会先单体 + 一台 RDS + 一个 Redis 跑着,等流量真上来再按这条路径演进,而不是一上来就过度设计。"——主动讲权衡是系统设计题的高分动作。
Q4:设计一套监控和日志系统?
我的答案:
我按"采集、缓冲、存储、展示、告警、容量"六块讲。
采集层:机器上跑 node_exporter 采系统指标,应用暴露 /metrics,日志用 Filebeat(K8s 里用 DaemonSet)采集。中间加一层缓冲:日志量突增时先入 Kafka/消息队列削峰,再让 ES 慢慢消费,避免把 ES 直接打垮——这是高可用的关键。
存储层:指标用 Prometheus,数据量大了用远端存储(Thanos/Mimir)做多副本和长期保留;日志存 Elasticsearch,按天建索引、设生命周期,热数据 SSD、冷数据降存储成本。展示层 Grafana 画大盘,Kibana 搜日志。告警层 Alertmanager 做分组、抑制、分级通知。
容量和扩展我会提:Prometheus 本身要做高可用双副本;ES 集群要多分片多副本,别把单分片搞太大;日志设保留周期(比如 30 天)自动清理,否则 ES 先写满。
设计原则一句话:采集端轻量、中间有削峰、存储可扩展、告警可执行。
Q5:系统设计题的答题框架是什么?
我的答案:
系统设计我不追求一步到位,而是按固定五步往下走,让面试官看到思路。
第一步澄清需求和规模:先反问——这个服务给谁用、日活多少、要支持读多还是写多、一致性要求多强?别上来就画架构。
第二步容量估算:就是 Q1 那套,把 QPS、带宽、存储用口算出来,证明我知道要撑多大。
第三步画核心组件和数据流:从接入层(DNS/CDN/SLB)到应用、缓存、数据库、消息队列,先画一个能跑通的最小可用版本,不追求一步到位上微服务。
第四步补高可用和扩展:在每个组件上加冗余、做主从、加缓存、加分库分表的演进路径。
第五步主动讲权衡和瓶颈:哪块是未来瓶颈、为了一致性牺牲了可用性还是反过来、为什么这么选。
我最想传达的态度是:没有完美架构,只有适合当前规模的权衡。先做简单能跑的,再随流量演进,比一上来堆一堆高大上组件更让面试官信任。