Article
分布式与微服务架构 —— 高级能力核心
7 分钟阅读
Java 后端学习路线 · 17 篇
原则:理解分布式理论比会用框架更重要。 CAP 定理 + BASE 理论 + 分布式事务 + 限流熔断 = 架构设计能力的基本功。
一、CAP 定理(★★★★★)
1.1 定义
CAP:分布式系统无法同时满足以下三点,只能三选二
C(Consistency)一致性:
所有节点同一时刻看到的数据相同
例:写入后立即读取,必须读到最新数据
A(Availability)可用性:
每个请求都能收到响应(不保证数据最新)
例:集群中部分节点挂了,系统仍可用
P(Partition Tolerance)分区容错性:
网络分区发生时系统仍能工作
例:节点之间网络中断,系统不崩溃
核心理解:P 在分布式系统中是必须保证的(网络分区不可避免),所以实际选型是 CP 还是 AP。
1.2 组件 CAP 选型
| 组件 | 模式 | 取舍 |
|---|
| Nacos | AP(默认)/ CP | 绝大多数场景用 AP,配置中心场景可切 CP |
| Eureka | AP | 宁可返回旧数据,也不拒绝服务 |
| Zookeeper | CP | Leader 选举期间集群不可用,牺牲可用性 |
| Consul | CP | 强一致性保证 |
二、BASE 理论
BASE = Basically Available(基本可用)+ Soft State(软状态)+ Eventually Consistent(最终一致性)
与 ACID 的关系:
- ACID 是传统关系型数据库的强一致性模型
- BASE 是分布式系统的弱一致性模型
- BASE 不是 ACID 的替代,而是补充
核心思路:既然无法做到强一致性(C),
不如让系统达到最终一致性(E),
换取更高的可用性(A)。
三、分布式事务(★★★★★)
3.1 三大方案对比
| 方案 | 一致性 | 性能 | 复杂度 | 适用场景 |
|---|
| Seata AT | 最终一致 | 中 | 低 | 传统单体拆分微服务 |
| Seata TCC | 最终一致 | 高 | 高 | 对一致性要求高的金融场景 |
| MQ 事务消息 | 最终一致 | 高 | 中 | 跨系统异步调用 |
| 本地消息表 | 最终一致 | 中 | 低 | 无分布式事务中间件的场景 |
| Saga | 最终一致 | 高 | 高 | 长事务链 |
3.2 Seata AT 模式原理
角色:
- TC(Transaction Coordinator):事务协调器,维护全局事务状态
- TM(Transaction Manager):事务管理器,发起/提交/回滚全局事务
- RM(Resource Manager):资源管理器,管理分支事务
执行流程(两阶段提交):
阶段一(执行):
1. TM 向 TC 申请开启全局事务
2. 各 RM 执行本地事务,并生成 Undo Log
3. 提交本地事务(!提交了),注册分支事务到 TC
阶段二(提交/回滚):
4. TM 通知 TC 提交或回滚
5. 提交:TC 通知各 RM 删除 Undo Log
6. 回滚:TC 通知各 RM 根据 Undo Log 回滚数据
关键:阶段一就提交了本地事务,阶段二才决定全局提交还是回滚。
回滚靠 Undo Log(执行反向 SQL)实现。
3.3 TCC 模式
TCC = Try(预留资源)+ Confirm(确认执行)+ Cancel(取消回滚)
以转账为例:
Try:冻结 A 账户 100 元(余额不减少)
Confirm:A 余额 -100,B 余额 +100
Cancel:解冻 A 账户 100 元
与 AT 的区别:
- AT 是自动生成反向 SQL,对业务无侵入
- TCC 需要业务方自己实现 Try/Confirm/Cancel 三个方法
- TCC 性能更好(无全局锁),但开发成本更高
四、分布式锁(★★★★☆)
4.1 Redis vs Zookeeper 方案对比
| 对比维度 | Redis | Zookeeper |
|---|
| 原理 | SET NX EX + Lua 脚本释放 | 临时顺序节点 + Watch |
| 性能 | 高(内存操作) | 中(有 Leader 选举开销) |
| 可靠性 | 可能丢失(异步复制) | 高(CP 保证) |
| 释放 | 需主动释放(WatchDog 续期) | 自动释放(Session 断开即删除) |
| 阻塞等待 | 自旋重试 | Watch 通知 |
| 适用 | 性能要求高、可容忍极低概率失效 | 一致性要求高(金融) |
五、分布式 ID 生成(★★★★☆)
| 方案 | 原理 | 优点 | 缺点 |
|---|
| UUID | 随机生成 | 无中心节点 | 不递增,作为主键影响插入性能 |
| 数据库号段 | 批量获取 ID 段 | 递增,实现简单 | 有单点风险 |
| 雪花算法 | 时间戳 + 机器 ID + 序列号 | 递增趋势,无中心节点 | 依赖时钟,时钟回拨有问题 |
| 美团 Leaf | 号段模式 + 雪花算法 | 生产验证 | — |
雪花算法 ID 结构(64 位):
1bit(不用)| 41bit 时间戳 | 10bit 机器 ID | 12bit 序列号
41bit 时间戳:约 69 年
10bit 机器 ID:1024 台机器
12bit 序列号:每毫秒 4096 个 ID
六、限流降级熔断(★★★★☆)
6.1 核心概念
限流(Rate Limiting):控制请求速率,超过阈值的排队或拒绝
降级(Degradation):系统负载高时,关闭非核心功能
熔断(Circuit Breaker):调用失败达到阈值,自动切断调用,快速失败
三者关系:
限流 → 主动控制流量,预防系统过载
降级 → 过载时的被动应急措施
熔断 → 依赖服务不可用时的保护机制
6.2 限流算法
| 算法 | 原理 | 优点 | 缺点 |
|---|
| 计数器 | 固定时间窗口计数 | 简单 | 临界突刺(窗口切换时被双倍流量打穿) |
| 滑动窗口 | 将窗口切分为小格子,按时间滑动 | 平滑 | 实现稍复杂 |
| 漏桶 | 请求入桶,匀速流出 | 流量整形 | 无法应对突发流量 |
| 令牌桶 | 匀速放入令牌,请求获取令牌后执行 | 允许突发流量 | — |
Sentinel 默认使用滑动窗口算法,支持 QPS 和并发线程数两种限流模式。
6.3 熔断策略
Sentinel 3 种熔断策略:
1. 慢调用比例:响应时间 > 阈值的请求比例 > 设定值 → 熔断
2. 异常比例:异常请求比例 > 设定值 → 熔断
3. 异常数:1 分钟内异常数 > 设定值 → 熔断
熔断状态机:
CLOSED →(触发熔断条件)→ OPEN →(熔断时间到)→ HALF_OPEN
├→ 探测成功 → CLOSED
└→ 探测失败 → OPEN
七、服务网关(★★★★☆)
7.1 Gateway vs Nginx
| 对比维度 | Spring Cloud Gateway | Nginx |
|---|
| 定位 | 微服务 API 网关 | 通用反向代理服务器 |
| 性能 | Netty 异步非阻塞,性能高 | C 语言,性能极高 |
| 动态路由 | ✓ 天然支持(配置中心) | 需要 lua 或 OpenResty |
| 鉴权 | ✓ Spring Security 集成 | 需要 lua 脚本 |
| 限流 | ✓ 内置 RequestRateLimiter | 需要额外模块 |
| 适用 | 微服务内部流量管理 | 入口层/静态资源/CDN |
典型架构:Nginx(外层,SSL/静态资源)→ Gateway(内层,鉴权/限流/路由)→ 微服务。
八、分布式 Session 与认证
8.1 方案对比
1. Session 黏性(Sticky Session):Nginx 按 IP hash 转发
→ 简单但不可靠(服务器宕机则 Session 丢失)
2. Session 复制:各服务器之间同步 Session
→ 不适合大规模集群(广播开销大)
3. 集中式 Session:Redis 存储 Session
→ 推荐方案,所有服务器共享 Redis
4. JWT 无状态认证:
→ 服务器不存任何会话信息,每次请求携带 Token
→ 优点:完全无状态,水平扩展友好
→ 缺点:Token 无法主动失效(需配合黑名单)
面试自查清单
□ CAP 定理三选二的本质理解(为什么 P 必须选?)
□ Seata AT vs TCC 的原理区别和适用场景
□ 雪花算法 64 位结构能画出来
□ 令牌桶和漏桶的核心区别
□ 熔断状态机 CLOSED→OPEN→HALF_OPEN→CLOSED 流程
□ Gateway vs Nginx 在微服务架构中的分层定位
□ Redis 分布式锁的演进(SETNX → Lua → Redisson → Redlock)
□ JWT vs Session + Redis 的选型依据