# 系统设计面试题
针对大规模系统架构设计的面试题,涵盖高并发、高可用、可扩展等核心设计原则。
# 一、大规模系统架构
Q1:设计一个支持千万级用户的 AI Agent 助手平台,需要支持多 Agent 并行、低延迟响应和对话历史管理,请描述架构和关键技术选型。
参考答案:
- 接入层:WebSocket 长连接 + API Gateway,无状态可水平扩展。
- Agent 引擎:以 LangGraph 定义 Agent 逻辑,无服务化(如阿里云函数计算)或 K8s Deployment 按并发自动扩缩。
- 状态存储:Redis Cluster 保存会话上下文和状态快照,MongoDB 或 PostgreSQL 存长期历史。
- 消息:使用 RocketMQ 解耦事件流,比如调用工具后的回调、审批通知。
- 向量检索:Milvus 集群存储知识库,近实时更新。
- LLM 调度:通过负载均衡调用多个模型实例或不同模型,实现 fallback。
- 多 Agent 协作:通过一个 Orchestrator Agent 拆解任务为子任务,并行分发给对应 Agent,汇总结果。
- 监控与降级:当 LLM 不可用或响应慢,自动切换缓存回复或兜底话术。
# 二、工作流引擎设计
Q2:设计一个工作流引擎,支持动态节点、分支汇聚与人工任务,你如何实现?和业务流程平台结合点在哪?
参考答案:
- 流程定义使用 BPMN 类似模型,以 JSON/XML 存储,节点类型:开始、结束、自动任务(脚本/API)、排他/并行网关、人工任务。
- 引擎内核:状态机推进 token,解析流程定义,计算下一节点。持久化到数据库记录流程实例和任务。
- 人工任务通过任务队列(pull/push)分发给用户,支持审批、填写表单。
- 动态节点:可在流程中通过脚本节点动态修改后续节点或增加子流程。
- 与业务流程平台结合:销售、结算等业务单据的生命周期由工作流引擎驱动,状态变更触发业务操作(如创建销退单),并回调业务系统。这样业务逻辑与流程控制解耦。
# 三、高并发系统设计
Q3:如何设计一个高并发秒杀系统?
参考答案:
# 架构设计
用户 → CDN → 负载均衡 → 网关 → 服务集群 → 数据库
↓
Redis集群 → MQ → 异步处理
# 核心要点
前端优化
- CDN 静态资源加速
- 页面静态化
- 按钮防重复点击(前端置灰+后端去重)
网关限流
- Nginx 限流
- Sentinel 网关流控
- IP 黑名单/验证码
缓存预热
- Redis 预加载商品库存
- 本地缓存热点数据
库存扣减
- Redis 原子操作:
DECR - 预扣库存,异步扣减数据库
- 库存分桶(多 key)减少竞争
- Redis 原子操作:
异步处理
- MQ 削峰填谷
- 订单异步创建
- 最终一致性保证
数据库优化
- 分库分表
- 读写分离
- 索引优化
# 四、分布式ID生成
Q4:分布式系统中如何生成全局唯一ID?
参考答案:
# 方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| UUID | 简单、本地生成 | 无序、过长、无业务含义 | 非核心业务 |
| 数据库自增 | 简单、有序 | 单点问题、性能瓶颈 | 小规模系统 |
| 号段模式 | 性能高、有序 | 需要数据库支持 | 中等规模 |
| Snowflake | 高性能、有序、分布式 | 时钟回拨问题 | 大规模分布式 |
| Redis INCR | 高性能 | Redis 挂了不可用 | 需要Redis的场景 |
# Snowflake算法详解
结构(64位):
0 - 41位时间戳 - 10位机器ID - 12位序列号
时间戳:41位,可用69年 机器ID:10位,支持1024台机器 序列号:12位,每毫秒4096个ID
代码实现:
public class SnowflakeIdWorker {
private final long twepoch = 1288834974657L;
private final long workerIdBits = 5L;
private final long datacenterIdBits = 5L;
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
private final long maxDatacenterId = -1L << datacenterIdBits;
private final long sequenceBits = 12L;
private final long workerIdShift = sequenceBits;
private final long datacenterIdShift = sequenceBits + workerIdBits;
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
private long workerId;
private long datacenterId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException("时钟回拨");
}
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift)
| sequence;
}
protected long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
protected long timeGen() {
return System.currentTimeMillis();
}
}
# 五、分布式锁
Q5:分布式锁的实现方案有哪些?各有什么优缺点?
参考答案:
# 实现方案对比
| 方案 | 实现方式 | 优点 | 缺点 |
|---|---|---|---|
| Redis | SETNX + 过期时间 | 性能高、实现简单 | 锁过期问题、主从切换丢锁 |
| Zookeeper | 临时有序节点 | 可靠性高、自动释放 | 性能较低、实现复杂 |
| 数据库 | 唯一索引 | 简单、可靠 | 性能差、无自动释放 |
| etcd | Lease + Revision | 高可用、强一致性 | 学习成本高 |
# Redis 分布式锁实现
加锁:
public boolean tryLock(String key, String value, long expireTime) {
return redisTemplate.opsForValue()
.setIfAbsent(key, value, expireTime, TimeUnit.SECONDS);
}
解锁(Lua脚本保证原子性):
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
# Redisson 实现
RLock lock = redissonClient.getLock("myLock");
try {
if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
// 执行业务逻辑
}
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
Redisson 优势:
- Watch Dog 自动续期
- 可重入锁
- 红锁(RedLock)解决主从切换问题
# 六、限流算法
Q6:常见的限流算法有哪些?如何实现?
参考答案:
# 1. 固定窗口计数器
实现:
public class FixedWindowRateLimiter {
private AtomicInteger counter = new AtomicInteger(0);
private long lastTime = System.currentTimeMillis();
private int limit = 100;
private long windowSize = 1000; // 1秒
public boolean tryAcquire() {
long now = System.currentTimeMillis();
if (now - lastTime > windowSize) {
counter.set(0);
lastTime = now;
}
return counter.incrementAndGet() <= limit;
}
}
缺点:窗口边界问题,可能出现2倍流量
# 2. 滑动窗口
实现:
public class SlidingWindowRateLimiter {
private LinkedList<Long> queue = new LinkedList<>();
private int limit = 100;
private long windowSize = 1000;
public synchronized boolean tryAcquire() {
long now = System.currentTimeMillis();
// 移除过期请求
while (!queue.isEmpty() && now - queue.peek() > windowSize) {
queue.poll();
}
if (queue.size() < limit) {
queue.offer(now);
return true;
}
return false;
}
}
优点:精度高 缺点:内存占用大
# 3. 漏桶算法
实现:
public class LeakyBucketRateLimiter {
private long capacity = 100;
private long rate = 10; // 每秒10个请求
private long water = 0;
private long lastTime = System.currentTimeMillis();
public synchronized boolean tryAcquire() {
long now = System.currentTimeMillis();
// 漏水
water = Math.max(0, water - (now - lastTime) * rate / 1000);
lastTime = now;
if (water < capacity) {
water++;
return true;
}
return false;
}
}
特点:恒定速率流出
# 4. 令牌桶算法
实现:
public class TokenBucketRateLimiter {
private long capacity = 100;
private long rate = 10; // 每秒生成10个令牌
private long tokens = 0;
private long lastTime = System.currentTimeMillis();
public synchronized boolean tryAcquire() {
long now = System.currentTimeMillis();
// 生成令牌
tokens = Math.min(capacity, tokens + (now - lastTime) * rate / 1000);
lastTime = now;
if (tokens > 0) {
tokens--;
return true;
}
return false;
}
}
优点:允许突发流量
# 5. Sentinel 实现
@SentinelResource(value = "test", blockHandler = "handleBlock")
public String test() {
return "success";
}
public String handleBlock(BlockException ex) {
return "blocked";
}
规则配置:
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("test");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(10);
rules.add(rule);
FlowRuleManager.loadRules(rules);
# 七、缓存架构设计
Q7:如何设计一个高可用的缓存架构?
参考答案:
# 多级缓存架构
应用 → 本地缓存 → Redis集群 → 数据库
# 缓存策略
缓存穿透防护
- 布隆过滤器
- 缓存空值(短TTL)
缓存击穿防护
- 互斥锁
- 逻辑过期
缓存雪崩防护
- 随机过期时间
- 多级缓存
- 熔断降级
# Redis 集群方案
| 方案 | 优点 | 缺点 |
|---|---|---|
| 主从 | 简单、读写分离 | 手动故障转移 |
| 哨兵 | 自动故障转移 | 配置复杂 |
| Cluster | 分布式、自动分片 | 不支持多键操作 |
# 八、消息队列架构
Q8:如何保证消息队列的可靠性?
参考答案:
# 生产者可靠性
确认机制
- RabbitMQ: Publisher Confirm
- RocketMQ: 同步发送+回调
重试机制
- 失败重试3次
- 超时告警
本地消息表
- 消息持久化到本地数据库
- 定时任务补偿发送
# 消费者可靠性
手动ACK
- 处理成功后再确认
- 失败重新入队
幂等性
- 唯一ID去重
- 数据库唯一约束
死信队列
- 多次失败进入死信
- 人工处理或告警
# 消息不丢失保证
生产者 → [confirm] → Broker → [持久化] → 消费者 → [ACK]
# 九、数据库架构设计
Q9:如何设计一个高可用的数据库架构?
参考答案:
# 主从复制
Master (写) → Slave1 (读)
→ Slave2 (读)
问题:
- 主从延迟
- 主库单点
# 双主架构
Master1 ↔ Master2
↓ ↓
Slave1 Slave2
问题:
- 数据冲突
- 复杂度高
# 分库分表
垂直拆分:按业务拆分
水平拆分:按数据量拆分
中间件:
- ShardingSphere
- MyCat
问题:
- 跨库JOIN
- 分布式事务
- 分页查询
# 读写分离 + 分库分表
┌→ Slave (读)
Master→
└→ Slave (读)
Master1 → Slave1
Master2 → Slave2
# 十、微服务架构设计
Q10:微服务架构的核心组件有哪些?如何选择?
参考答案:
# 核心组件
| 组件 | 功能 | 常用方案 |
|---|---|---|
| 注册中心 | 服务发现 | Nacos、Eureka、Consul |
| 配置中心 | 配置管理 | Nacos、Apollo、Spring Cloud Config |
| 网关 | 路由、限流、鉴权 | Spring Cloud Gateway、Kong、Zuul |
| 负载均衡 | 流量分发 | Ribbon、LoadBalancer |
| 熔断降级 | 容错保护 | Sentinel、Hystrix、Resilience4j |
| 链路追踪 | 调用链监控 | SkyWalking、Zipkin、Jaeger |
| 分布式事务 | 跨服务事务 | Seata、RocketMQ事务消息 |
# 技术选型建议
Spring Cloud Alibaba:
- 注册中心:Nacos
- 配置中心:Nacos
- 熔断降级:Sentinel
- 分布式事务:Seata
Spring Cloud Netflix:
- 注册中心:Eureka
- 配置中心:Spring Cloud Config
- 熔断降级:Hystrix
- 网关:Zuul
Spring Cloud:
- 网关:Spring Cloud Gateway
- 负载均衡:Spring Cloud LoadBalancer
- 链路追踪:Micrometer Tracing