如何设计一个系统
-
设计一个高并发系统(以秒杀为例)
先定目标: 峰值QPS、成功率、库存一致性、用户体验
架构拆解
2 流量入口
CDN + 静态资源缓存
接入层(Nginx / 网关)
👉 目的:挡掉80%无效流量3 限流(第一道防线)
IP限流
用户限流
接口令牌桶
👉 防止系统被打爆4 读写分离(核心优化)
商品信息:缓存(Redis)
库存:缓存 + 原子扣减
👉 关键点:
Redis 扣库存(decr)
避免数据库扛高并发5 异步削峰(关键)
下单请求 → MQ(Kafka / RocketMQ)
后端慢慢消费
👉 目的:
把瞬时高并发 → 平滑流量6 最终一致性
数据库最终落库
失败补偿(重试 / 死信队列) -
如何设计一个高可用服务(99.99%)
-
多副本(基础)
服务多实例部署
负载均衡(Nginx / SLB) -
去单点(核心)
数据库主从
Redis哨兵 / 集群
MQ集群 -
故障隔离
微服务隔离
线程池隔离
资源隔离 -
自动恢复
健康检查
自动重启(K8s) -
降级策略(关键)
非核心功能关闭
返回默认值 -
监控体系
指标(QPS、RT、错误率)
日志 + 链路追踪(SkyWalking)
-
-
如何设计限流、降级、熔断
a 限流(防止被压垮)
1️⃣ 接入层限流
位置: Nginx / API网关:
方法: IP限流 / URL限流
目的: 挡住恶意流量,减轻后端压力
2️⃣ 应用层限流
位置: 服务内部 ,接口级/用户级
3️⃣ 分布式限流
使用Redis 统一计数
4️⃣ 数据层限流
数据库连接池限制
MQ消费速率限制
常用算法:
固定窗口: 每秒最多N次
滑动窗口: 把时间切成多个小窗口(始终最近一秒内多少次)
漏桶算法: 请求进桶,以固定速率处理
令牌桶: 系统按速率发令牌,请求必须拿令牌才能执行b 降级
必要时关闭非核心功能, 返回兜底数据c 熔断
下游服务挂了,防止扩散;
一般通过失败率、超时率等指标触发熔断,并进入打开状态,此时不再调用下游,而是执行降级逻辑。
之后通过半开状态进行探测恢复,确保系统能够平稳恢复服务。
在实际系统中,熔断通常会和限流、降级结合使用,形成完整的容错体系。
性能优化
一个接口从 200ms → 2s,你怎么排查?
第一,先看监控,判断是流量问题还是内部性能问题,并定位慢在网关、应用还是下游依赖;
第二,通过链路追踪(如 SkyWalking)定位具体慢在哪个调用;
第三,根据慢点分类排查,比如数据库慢查询、缓存失效、线程池阻塞、GC、外部依赖等;
同时我会结合发布记录,看是否是上线导致,并优先考虑回滚验证。
整体目标是快速缩小范围,而不是直接猜原因。
接口耗时拆分
网关耗时 如果网关就慢 → 网络 / 限流
应用耗时 如果应用慢 → 代码 / 线程池
下游调用耗时 如果下游慢 → DB / Redis / 外部服务
QPS + RT + 错误率
流量暴涨(压垮)
RT 上升但 QPS 不变(内部问题)
错误率上升(重试导致放大)
JVM / 系统指标
CPU 飙高?
GC 次数变多?
线程数暴涨?
数据库 / 缓存指标
慢 SQL
连接池是否打满
Redis 是否阻塞
常见原因:
1 数据库问题
SQL 没走索引
大表扫描
锁等待(行锁/表锁)
连接池耗尽
2 缓存失效 / 穿透(DB QPS 突然暴涨)
Redis key 过期
大量请求打到 DB
3 线程池问题
线程池满 → 排队
队列过长 → RT 变慢
4 外部依赖慢
第三方接口
RPC 调用
数据库慢查询如何定位
1 定位具体慢 SQL
方法1:慢查询日志
方法2:实时查看正在执行的 SQL
方法3:应用日志
2 分析 SQL 为什么慢
看执行计划 重要看: type ,key,rows
常见问题:
1. 没走索引(where 没命中索引,or 导致失效,使用函数或计算,隐式类型转换,LIKE 以 % 开头)
2. 扫描数据太多
3. 排序慢
4. join 不合理(大表 join 大表)
5. 索引设计不合理
如何做缓存设计(Redis)
1 合理设计 key 和 TTL,并根据业务选择合适的数据结构
2 重点处理缓存三大问题:穿透、击穿和雪崩,比如通过布隆过滤器、互斥锁和随机过期解决;
3 保证缓存与数据库的一致性,通常采用"先更新数据库再删除缓存"的策略,必要时使用延迟双删;
4 针对高并发场景,会设计多级缓存、热点数据预热和限流降级机制,保证系统稳定性。
-
稳定性 / 线上问题
线上CPU 100%,你怎么处理?a 先止血, 防止业务继续恶化
限流,降级,扩容,b 快熟定位问题
使用top 找到高cpu进程
使用jstack看线程栈常见原因:
死循环
频繁GC
序列化
锁竞争
大量计算任务
内存泄漏怎么排查
现象: 内存持续上涨,最后甚至服务挂掉
dump 堆,用 MAT 分析大对象和引用链,定位泄漏源
常见原因:
静态集合(List / Map)
缓存没清理
ThreadLocal 未释放
连接没关闭
架构设计
如何设计一个系统
1. 先定边界 : 搞清楚「为什么做、做什么、不做什么」
a 业务对齐
业务目标对齐(业务价值是什么?)
关键指标(QPS,数据量,响应时间,可用性等)
用户群体(用户对象是是谁)
约束: 成本/技术栈/人力
b 明确需求边界 & 范围
要做什么:核心能力、核心流程
绝不做什么:砍掉边缘需求、避免过度设计
依赖哪些外部系统?哪些系统依赖我?
c 梳理核心业务流程
画出主干流程,只保留关键节点,砍掉分支异常,先保证主链路跑通。
2. 需求建模:从业务→领域→数据
划分业务
划分模块
数据建模
3. 架构设计
技术选型
整体架构
分层架构
模块拆分 & 接口设计
4. 架构评审 & 风险复盘
架构评审:业务合理性、复杂度、扩展性、性能、安全、成本
列出所有风险点:性能风险、数据风险、依赖风险、上线风险
每个风险给出:规避方案、应急预案、责任人
技术方案如何支持业务增长?
阶段1:0 → 1(验证阶段)
目标:快速上线,验证业务
方案: 简单架构, 快比完美更重要
阶段2:1 → 10(增长阶段)
目标: 系统能扛住增长
方案: 引入缓存, 拆分服务,异步化
(通常采用的方案是,负载均衡,加几台机器快速上线)
阶段3:10 → 100(规模阶段)
目标: 高并发 + 高可用
方案: 微服务,分库分表,读写分离,削峰,限流,熔断,降级
主要解决: 高并发,数据量暴涨
阶段4:100 → ∞(成熟阶段)
目标:稳定性 + 体系化
方案: 多机房/多活, 自动扩缩容,完整的监控体系
如果业务要快上线,你如何取舍技术债?
不能背的技术债
1. 稳定性底线 核心链路容错、幂等、防重、基础限流、参数校验、事务兜底,不能欠。
2. 数据安全 & 合规底线 敏感数据脱敏、基础鉴权权限、接口防刷、基础日志留痕,不能裸奔上线。
3. 可运维 & 可回滚底线 基础监控告警、链路日志、版本可灰度、一键回滚、故障隔离能力
4. 服务拆分边界、依赖关系、领域分层不能乱
可以背的技术债
5. 硬编码代替配置化
6. 临时写死逻辑
7. 部分设计评审,只做核心审核
如何评估一个技术方案 ROI?
ROI = 收益/成本
成本评估: 开发成本, 硬件成本, 运维成本,风险成本
收益评估: 性能提升, 稳定性提升, 降低成本, 业务收益,风险规避收益
如何复盘一个项目
项目复盘的核心是: 总结经验、发现问题、沉淀方法,并指导下一次更好地做
开场先定调:不追责、只找问题、只为下次更好。
复盘步骤:
1. 项目背景 & 目标回顾
2. 实际结果 vs 预期目标 (进度,范围,质量,成本)
3. 亮点沉淀(业务,技术,执行 ),能复制到下一个项目上
4. 问题 & 根因分析,避免下次再出现
5. 最后沉淀规范