基于黑马教程——微服务架构解析(二):雪崩防护+分布式事务
之前的两篇文章我们介绍了微服务的基础概念及其服务间通信机制。本篇将深入探讨微服务的核心保障:服务保护与分布式事务。
一、微服务保护
问题描述:
在一个购物车的微服务中,倘若某一项服务(服务A)同一时刻访问的数据十分庞大,但是购物车服务Tomcat的线程数据是有限的,这会导致整个购物车服务崩溃。倘若这个购物车服务又和别的微服务进行关联,这样一级连一级,最终可能导致整个微服务网络的崩溃,也被称做“雪崩”。
解决方法:
服务保护的方案有很多,最典型这几种:
- 请求限流
- 线程隔离
- 服务熔断
这些方法都不用我们亲自一一实现,已经有一个组件把这些集成了起来,因此我们只需要学习这个组件就行了——Sentinel
1.1 Sentinel
Sentinel 是阿里巴巴开源的一款 轻量级流量控制、熔断降级和系统保护组件,专注于解决微服务架构中的 高可用性、稳定性 问题。它提供实时的监控和动态规则配置,帮助开发者保障服务在 高并发、依赖故障、突发流量 等场景下的稳定性。
核心功能:
- 流量控制(Flow Control):精准控制QPS、并发线程数,防止系统过载。
- 熔断降级(Circuit Breaking):自动检测异常比例/响应时间,触发熔断保护。
- 系统自适应保护(System Adaptive Protection):智能调整入口流量,保护系统不被压垮。
- 实时监控(Real-time Monitoring):可视化查看接口调用情况、限流熔断数据。
1.2 请求限流
核心作用:通过精准控制单位时间内的请求量,防止突发流量导致系统过载崩溃。
实现原理:
- 设定QPS(每秒查询量)或并发线程数阈值
- 超出阈值的请求将被立即拒绝或排队等待
- 支持多种算法:固定窗口、滑动窗口、漏桶、令牌桶等
典型应用场景:
- 秒杀系统的高峰期流量控制
- API网关的全局流量管控
- 核心业务接口的访问保护
1.3 线程隔离
核心机制:通过为每个微服务子服务分配独立的执行线程池,实现故障隔离。
关键优势:
- 资源隔离:单个子服务的线程池耗尽不会影响其他服务
- 故障隔离:崩溃的线程仅影响当前服务实例
- 弹性伸缩:可根据服务重要性动态调整线程池大小
实现方式对比:
隔离策略 | 实现方式 | 适用场景 | 资源消耗 |
---|---|---|---|
线程池隔离 | 每个服务独立线程池 | 耗时较长的同步调用 | 较高 |
信号量隔离 | 计数器控制并发数 | 轻量级快速调用 | 较低 |
最佳实践:
- 关键服务配置更大的线程池
- 配合熔断机制实现双重保护
- 通过监控实时调整线程池参数
补充说明:
虽然线程隔离能有效防止级联故障,但仍需配合熔断机制使用。当某服务线程池完全耗尽时,熔断器可以快速失败并启动降级策略,避免请求堆积。
1.4 服务熔断
当系统检测到某个子服务即将崩溃(如响应时间飙升、错误率激增)时,直接阻断对该服务的所有请求,并快速返回一个预设的备选结果(Fallback),从而避免级联故障。
所以,我们要做两件事情:
- 编写服务降级逻辑:就是服务调用失败后的处理逻辑,根据业务场景,可以抛出异常,也可以返回友好提示或默认数据。
- 异常统计和熔断:统计服务提供方的异常比例,当比例过高表明该接口会影响到其它服务,应该拒绝调用该接口,而是直接走降级逻辑。
三者对比
保护策略 | 核心机制 | 主要作用 | 触发条件 | 实现方式 | 适用场景 | 代表框架 |
---|---|---|---|---|---|---|
请求限流 | 控制单位时间请求量 | 防止突发流量压垮系统 | QPS或并发数超过阈值 | - 计数器算法 - 漏桶/令牌桶算法 | - 秒杀系统 - API网关限流 | Sentinel、Redis RateLimit |
线程隔离 | 资源隔离(线程池/信号量) | 避免单个服务耗尽所有线程资源 | 线程池满/信号量耗尽 | - 独立线程池 - 信号量计数 | - 同步阻塞调用 - 耗时操作隔离 | Hystrix、Sentinel |
服务熔断 | 快速失败+自动恢复 | 防止级联故障,提升系统可用性 | 错误率/慢调用比例超过阈值 | - 熔断器状态机(开/半开/关) - 降级策略 | - 弱依赖服务 - 第三方接口调用 | Sentinel、Resilience4j |
二、分布式事务
在分布式系统中,一个业务执行需要多个微服务共同参与。以图中为例,整个业务为购买商品事务,交易服务、购物车服务和库存服务为分支事务。在单体项目中,很容易满足事务ACID原则,但是在分布式如何满足?
2.1 Seata
核心定位:阿里巴巴开源的 一站式分布式事务解决方案,提供 AT、TCC、Saga、XA 多种模式,解决微服务架构下的数据一致性问题。
Seata的事务管理中有三个重要的角色:
- TC (Transaction Coordinator) - 事务协调者:维护全局和分支事务的状态,协调全局事务提交或回滚。
- TM (Transaction Manager) - 事务管理器:定义全局事务的范围、开始全局事务、提交或回滚全局事务。
- RM (Resource Manager) - 资源管理器:管理分支事务,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
TM 就是全局事务的管理者,由这个决定什么时候开启事务,什么时候提交和回滚事务,RM 就是针对自己的分支事务进行汇报,分支事务的回滚和提交。TC 其实就先相当于一个中间人, 监控所有RM 状态汇报给到TM,然后什么操作有TM决定
而TC服务则是事务协调中心,是一个独立的微服务,需要单独部署
2.2 Seata的XA模型
RM
一阶段的工作:
- 注册分支事务到
TC
- 执行分支业务sql但不提交
- 报告执行状态到
TC
TC
二阶段的工作:
TC
检测各分支事务执行状态- 如果都成功,通知所有RM提交事务
- 如果有失败,通知所有RM回滚事务
RM
二阶段的工作:
- 接收
TC
指令,提交或回滚事务
2.3 Seata的AT模型
阶段一RM
的工作:
- 注册分支事务
- 记录undo-log(数据快照)
- 执行业务sql并提交
- 报告事务状态
阶段二提交时RM
的工作:
- 删除undo-log即可
阶段二回滚时RM
的工作:
- 根据undo-log恢复数据到更新前
2.4 两个模型之间的区别
对比维度 | AT模型(自动补偿) | XA模型(两阶段提交) |
---|---|---|
一致性 | 最终一致性(存在短暂中间状态) | 强一致性(全程数据锁定) |
性能 | ⭐⭐⭐⭐(一阶段已提交,无阻塞) | ⭐⭐(同步阻塞,资源长时间锁定) |
侵入性 | 低侵入(无需改造业务代码) | 低侵入(依赖数据库原生XA协议) |
实现复杂度 | 简单(自动生成反向SQL) | 中等(需数据库支持XA) |
锁范围 | 全局行锁(仅二阶段冲突检测时短暂加锁) | 全程行锁(Prepare阶段即锁定) |
补偿机制 | 自动生成undo_log 反向SQL | 依赖数据库回滚(无自动补偿) |
适用场景 | 高并发OLTP场景(如电商、库存) | 传统金融系统(如银行核心账务) |
数据库支持 | 支持主流关系型数据库(MySQL/Oracle等) | 需数据库明确支持XA协议(如MySQL InnoDB) |
故障恢复 | 依赖undo_log 恢复(需保证日志可靠) | 依赖数据库日志恢复 |
典型框架 | Seata默认模式 | Seata XA模式、传统JTA |