微服务架构
微服务架构 #
分布式系统设计核心,涵盖服务拆分、服务治理、分布式事务等
📋 目录 #
微服务拆分原则 #
核心原则 #
拆分方法 #
| 方法 | 说明 | 示例 |
|---|---|---|
| 业务功能拆分 | 按功能模块拆分 | 电商:用户、商品、订单、支付 |
| 数据模型拆分 | 数据独立性 | 每个服务独占地库 |
| 用户角色拆分 | 按角色权限 | 管理员服务、员工服务、客户服务 |
拆分流程 #
1. 业务分析
- 分析业务模块关系
- 识别服务边界
2. 确定拆分粒度
- 太细:服务太多,管理复杂
- 太粗:无法发挥微服务优势
3. 定义服务边界
- 明确职责范围
- 定义接口契约
4. 数据迁移
- 垂直拆表(按业务)
- 数据清理
5. 代码重构
- 提取服务代码
- 去除循环依赖
6. 测试部署
- 单元测试
- 集成测试
- 灰度发布
拆分收益与挑战 #
| 收益 | 挑战 |
|---|---|
| ✅ 独立部署扩展 | ❌ 运维复杂度增加 |
| ✅ 技术栈灵活 | ❌ 分布式事务 |
| ✅ 可维护性提升 | ❌ 服务间通信开销 |
| ✅ 团队自治 | ❌ 数据一致性 |
服务治理 #
注册中心选型 #
| 对比项 | Eureka | Nacos | Consul | Zookeeper |
|---|---|---|---|---|
| 一致性模式 | AP | AP/CP | CP | CP |
| 健康检查 | 客户端 | TCP/HTTP/K8s | TCP/HTTP/Script | KeepAlive |
| 配置中心 | ❌ | ✅ | ✅ | ❌ |
| Spring Cloud集成 | ✅ | ✅ | ✅ | ✅ |
| 适用场景 | 已有项目 | 新项目 | K8s环境 | 遗留项目 |
服务发现 #
// 客户端服务发现
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/api/users/{id}")
User getUser(@PathVariable Long id);
}
// 调用流程
// 1. Ribbon从注册中心获取可用服务列表
// 2. 选择一个实例(负载均衡)
// 3. 发起HTTP请求
负载均衡算法 #
| 算法 | 说明 | 适用场景 |
|---|---|---|
| 轮询 | 依次轮转 | 服务器性能相当 |
| 随机 | 随机选择 | 大量并发 |
| 加权轮询 | 按权重轮转 | 服务器性能不均 |
| 最小连接 | 选择连接最少 | 长连接场景 |
| 一致性哈希 | 相同请求落同一服务器 | 有状态服务 |
熔断降级 #
Sentinel 示例:
@SentinelResource(
value = "getUser",
blockHandler = "handleBlock" // 降级处理
)
public User getUser(Long id) {
return userRepository.findById(id);
}
public User handleBlock(Long id, BlockException ex) {
// 降级逻辑:返回缓存数据或默认值
return User.builder().name("降级用户").build();
}
限流算法 #
| 算法 | 原理 | 优缺点 | 适用场景 |
|---|---|---|---|
| 固定窗口 | 单位时间计数 | 简单粗暴,边界突变 | 基础限流 |
| 滑动窗口 | 窗口滑动计数 | 更平滑 | 精确限流 |
| 令牌桶 | 固定速率放入令牌 | 允许突发流量 | 保护自身服务 |
| 漏桶 | 固定速率漏出 | 强制平滑输出 | 保护下游服务 |
// Sentinel 限流
@SentinelResource(
value = "getUser",
blockHandler = "handleBlock"
)
public User getUser(Long id) {
return userRepository.findById(id);
}
// 配置规则
// 资源名: getUser
// 限流阈值: 100 QPS
分布式事务 #
2PC 两阶段提交 #
第一阶段: 准备 (Prepare)
协调者 ───────> 参与者A: 准备提交
参与者B: 准备提交
参与者C: 准备提交
第二阶段: 提交/回滚 (Commit/Rollback)
协调者 ───────> 参与者A: 提交
参与者B: 提交
参与者C: 提交
| 优点 | 缺点 |
|---|---|
| ✅ 强一致性 | ❌ 同步阻塞 |
| ✅ 简单易理解 | ❌ 单点故障 |
TCC 补偿事务 #
Try 阶段:
- 资源预占
- 数据预处理
Confirm 阶段:
- 确认执行
- 提交业务
Cancel 阶段:
- 取消执行
- 回滚数据
示例: 电商下单
Try: 1. 预扣库存 2. 创建订单(待支付) 3. 扣减优惠券
Confirm: 订单状态→已支付
Cancel: 1. 释放库存 2. 删除订单 3. 返还优惠券
Saga 模式 #
| 模式 | 说明 |
|---|---|
| 编排式 | 中心协调器控制流程 |
| 协同式 | 服务间事件触发 |
示例:
// 订单Service
public void createOrder(Order order) {
try {
// 1. 创建订单
orderService.create(order);
// 2. 扣库存
inventoryService.deduct(order);
// 3. 扣优惠券
couponService.deduct(order);
// 4. 支付
paymentService.pay(order);
// 5. 确认订单
orderService.confirm(order.getId());
} catch (Exception e) {
// 补偿执行
// 返还优惠券 → 恢复库存 → 取消订单
}
}
Seata AT 模式 #
一阶段: 业务SQL执行
- 解析SQL语义
- 查询前镜像数据
- 执行业务SQL
- 查询后镜像数据
- 保存undo log
- 提交本地事务(释放锁)
二阶段: 提交/回滚
- 提交: 异步删除undo log
- 回滚: 根据undo log反向生成补偿SQL
三高架构 #
高可用 (High Availability) #
可用率: 99.99% (全年停机不超过52.6分钟)
实现:
1. 冗余设计
- 主从、集群、多活
2. 故障转移
- 心跳检测
- 自动切换
3. 负载均衡
- 流量分发
- 健康检查
4. 熔断降级
- 快速失败
- 保护系统
典型: 金融系统 7×24h不间断服务
高性能 (High Performance) #
关键指标:
- QPS (Queries Per Second)
- TPS (Transactions Per Second)
- 延迟 Latency (P95, P99)
优化手段:
1. 异步化处理
- 消息队列
2. 多级缓存
- 本地缓存 + Redis
3. 并行计算
- 分片处理
4. 代码优化
- 减少锁竞争
- I/O优化
典型: 秒杀系统 10万+ QPS
高扩展 (High Scalability) #
扩展方式:
- 水平扩展 (Scale-Out): 增加节点
- 垂直扩展 (Scale-Up): 提升配置
设计原则:
- 无状态服务
- Session外置Redis
- 松耦合架构
- 微服务独立部署
- 数据分片
- 分库分表
典型: 云平台自动扩缩容
CAP 理论 #
| 选择 | 说明 | 适用场景 |
|---|---|---|
| CP | 强一致性 + 分区容错 | 金融交易、ZooKeeper |
| AP | 高可用 + 分区容错 | 社交网络Redis |
| CA | 一致性 + 可用性 | 单机数据库 |
BASE 理论:
- BA (Basically Available): 基本可用
- S (Soft State): 软状态
- E (Eventually Consistent): 最终一致性
实战案例 #
订单超时关闭 #
方案一: 延迟消息 (推荐)
流程:
1. 创建订单后发送延迟消息 (30分钟后)
2. 消息到期触发关闭订单
3. 幂等性校验 (订单状态)
技术: RocketMQ Delay Message
优势:
- 精准时延
- 高吞吐
- 解耦
方案二: 定时扫描 (兜底)
流程:
1. 定时扫描待支付订单
2. 检查创建时间 > 30分钟
3. 批量关闭
技术: ElasticJob、XXL-Job
优化:
- 分片扫描
- 索引优化 (status + create_time)
限流降级策略 #
// 多级限流
第一级: 网关层
- 基于IP限流
- 基于用户限流
第二级: 服务层
- 接口级限流
- 方法级限流
第三级: 数据层
- SQL限流
- 连接池保护
// 白名单机制
if (whiteList.contains(userId)) {
// 白名单用户不限流
return;
}
面试题汇总 #
基础 #
- 微服务拆分原则?
- 单体 → 微服务迁移策略?
- 微服务 vs 分布式区别?
- 服务治理包含哪些?
注册中心 #
- Eureka vs Nacos vs Consul?
- 服务发现原理?
- 注册中心高可用方案?
服务调用 #
- OpenFeign vs RestTemplate?
- 负载均衡算法?
- 服务端负载均衡 vs 客户端负载均衡?
熔断降级 #
- 熔断器三种状态?
- 熔断 vs 降级 vs 限流?
- Sentinel vs Hystrix?
分布式事务 #
- 2PC原理及缺点?
- TCC事务流程?
- Saga模式补偿机制?
- Seata AT原理?
高并发 #
- 秒杀系统设计?
- 如何避免超卖?
- 三 high 设计?
面试题答案详解 #
基础篇 #
- 微服务拆分原则?
答案:
| 原则 | 说明 |
|---|---|
| 单一职责 | 每个服务只干一件事 |
| 高内聚低耦合 | 内部紧密,外部依赖少 |
| 按业务领域 | DDD限界上下文划分 |
| 独立部署发布 | 能单独上线 |
| 团队自治 | 一个团队维护一个服务 |
常见拆分方法:
- 按业务功能(用户/商品/订单)
- 按数据模型
- 按用户角色
- 单体 → 微服务迁移策略?
答案:
| 策略 | 说明 |
|---|---|
| 绞杀者模式 | 新建微服务,逐步替换旧系统 |
| 气泡模式 | 逐步把功能抽出来 |
| DB优先 | 先拆库,再拆服务 |
推荐步骤:
- 先拆边缘功能
- 后拆核心功能
- 灰度发布验证
- 用消息队列解耦
- 微服务 vs 分布式区别?
答案:
| 对比 | 微服务 | 分布式 |
|---|---|---|
| 关注点 | 服务拆分、服务治理 | 多节点协作 |
| 场景 | 系统拆分 | 性能、高可用 |
| 关系 | 微服务是分布式的子集 | 分布式 > 微服务 |
总结:
- 微服务 ≈ 分布式服务架构
- 分布式系统不一定是微服务
- 服务治理包含哪些?
答案:
注册中心 #
- Eureka vs Nacos vs Consul?
答案:
| 对比 | Eureka | Nacos | Consul |
|---|---|---|---|
| CAP | AP | AP/CP | CP |
| 健康检查 | Client心跳 | TCP/HTTP/MySQL | Script |
| 配置中心 | ❌ | ✅ | ✅ |
| 推荐 | 旧项目 | 新项目 | 多数据中心 |
推荐: 新项目选Nacos(注册中心+配置中心二合一)
- 服务发现原理?
答案:
两种模式:
| 模式 | 说明 |
|---|---|
| 客户端发现 | 自己拉取列表,自己选(Ribbon) |
| 服务端发现 | 通过网关/负载均衡器(Nginx) |
- 注册中心高可用方案?
答案:
集群部署:
- Eureka: 多节点互相注册
- Nacos: 集群模式
- Consul: Server集群
高可用要点:
- 节点数3/5/7(奇数,避免脑裂)
- 跨机房部署
- 数据持久化
服务调用 #
- OpenFeign vs RestTemplate?
答案:
| 对比 | RestTemplate | OpenFeign |
|---|---|---|
| 写法 | 手动拼接URL | 声明式接口 |
| 集成 | 需手动配置 | 自动集成Ribbon/Sentinel |
| 推荐 | ❌ | ✅ |
OpenFeign示例:
@FeignClient("user-service")
public interface UserClient {
@GetMapping("/api/users/{id}")
User getUser(@PathVariable Long id);
}
- 负载均衡算法?
答案:
| 算法 | 说明 |
|---|---|
| 轮询 | 挨个顺序来(默认) |
| 随机 | 随机选 |
| 加权轮询 | 权重高的分配多 |
| 最少连接 | 选连接数最少的 |
| 一致性哈希 | 相同请求落同一服务 |
- 服务端负载均衡 vs 客户端负载均衡?
答案:
| 对比 | 服务端 | 客户端 |
|---|---|---|
| 实现 | Nginx/网关 | Ribbon/LoadBalancer |
| 优缺点 | 统一管理,多一跳 | 少一跳,灵活 |
| 推荐 | 混合使用(网关+客户端) |
熔断降级 #
- 熔断器三种状态?
答案:
状态说明:
- Closed: 正常,请求放行
- Open: 熔断,快速失败
- HalfOpen: 半开,尝试放行少量请求
- 熔断 vs 降级 vs 限流?
答案:
| 对比 | 熔断 | 降级 | 限流 |
|---|---|---|---|
| 目的 | 防雪崩 | 保核心 | 防过载 |
| 触发 | 错误率高 | 资源不足 | QPS超阈值 |
| 示例 | 下游挂了 | 返回默认值 | 排队/拒绝 |
- Sentinel vs Hystrix?
答案:
| 对比 | Hystrix | Sentinel |
|---|---|---|
| 状态 | 停更 | 活跃 |
| 功能 | 基本熔断 | 限流+熔断+热点+系统保护 |
| 控制台 | 简单 | 丰富 |
| 推荐 | ❌ | ✅ |
分布式事务 #
- 2PC原理及缺点?
答案:
2PC = 两阶段提交
阶段1: Prepare(协调者问各参与者:准备好了没?)
阶段2: Commit/Rollback(根据回答结果决定提交或回滚)
缺点:
- 同步阻塞
- 单点故障
- 数据不一致风险
- TCC事务流程?
答案:
TCC = Try-Confirm-Cancel
| 阶段 | 说明 |
|---|---|
| Try | 资源预占 |
| Confirm | 确认提交 |
| Cancel | 补偿回滚 |
- Saga模式补偿机制?
答案:
Saga = 长事务 + 补偿
两种实现:
- 编排式: 中心协调者控制
- 协同式: 服务间事件驱动
核心: 每个事务都有对应的补偿事务
- Seata AT原理?
答案:
AT = 自动补偿事务
1. 一阶段: 执行业务SQL,保存镜像,提交
2. 二阶段: 提交(删除镜像)或回滚(根据镜像生成反向SQL)
优点: 对代码侵入性低,推荐
高并发 #
- 秒杀系统设计?
答案:
核心思路:
1. 前端: 按钮置灰、倒计时、防抖
2. 网关: 限流、防重复、WAF
3. 服务: Redis预扣库存、消息队列异步下单
4. 数据库: 乐观锁、分库分表、消息表
技术要点:
- 热点数据放Redis
- 消息队列削峰
- 限流降级保护
- 幂等性保证
- 如何避免超卖?
答案:
| 方案 | 说明 |
|---|---|
| 数据库乐观锁 | update stock set count=count-1 where id=? and count>0 |
| Redis Lua脚本 | 原子操作 |
| Redis Decr | 单线程原子 |
| 分布式锁 | 保证只有一个能下单 |
- 三高设计?
答案:
| 高 | 说明 |
|---|---|
| 高性能 | 响应快、QPS高(缓存、异步、优化) |
| 高可用 | 不宕机(集群、降级、熔断) |
| 高并发 | 扛得住(水平扩展、无状态、异步解耦) |
🔗 相关笔记 #
最后更新: 2026-04-29