架构(02):微服务拆分——限界上下文、数据一致性、服务间调用、演进策略
更新时间:2026-09-02。本文是
architecture/架构领域第 02 篇,接 分层架构。微服务拆分的核心不是"怎么拆"而是"拆了之后怎么处理数据一致性和服务间调用"。拆错了,后果比不拆还严重。
本文要回答的问题
- 微服务按什么维度拆分?按业务、按功能、还是按团队?
- 限界上下文(Bounded Context)是什么?怎么确定边界?
- 拆了之后,跨服务的数据一致性怎么保证?不用分布式事务?
- 服务间调用用同步(HTTP/gRPC)还是异步(消息队列)?
- 演进策略:先拆什么,后拆什么?什么时候不该拆?
一、拆分原则:按限界上下文拆分
限界上下文(Bounded Context)是 DDD 的概念
每个限界上下文:
- 一个独立的业务领域
- 有自己统一的业务语言(Ubiquitous Language)
- 有自己的数据模型
- 有明确的边界
示例:电商系统
订单上下文:订单、订单项、配送地址
库存上下文:库存、仓库、入库/出库
支付上下文:支付单、交易记录、退款
用户上下文:用户、地址、积分
每个上下文独立成一个微服务
每个服务有自己的数据库
上下文之间通过接口通信拆分原则:
1. 按业务领域拆分,不是按功能拆分
✅ 订单服务、支付服务、库存服务
❌ 读服务、写服务、日志服务
2. 拆分的粒度:一个团队维护 2-3 个服务
服务多了,维护成本 > 收益
3. 数据独立性:每个服务有自己的数据库
不共享数据库,否则耦合
4. 独立部署:每个服务可以独立部署
不影响其他服务二、服务间通信
| 通信方式 | 同步 | 异步 | 典型场景 |
|---|---|---|---|
| HTTP REST | 同步 | — | 查询、简单操作 |
| gRPC | 同步 | — | 高性能场景 |
| 消息队列 | — | 异步 | 事件通知、解耦 |
| 事件总线 | — | 异步 | 领域事件 |
同步调用(REST/gRPC)
优点:
- 简单,开发效率高
- 实时响应,适合查询
缺点:
- 调用链长,延迟叠加
- 服务强依赖,一个服务挂了,上游也挂了
- 不适合长事务
适用场景:
- 查询
- 简单操作,不需要跨服务协调异步调用(消息队列)
优点:
- 解耦,服务之间不直接依赖
- 削峰填谷,缓冲流量
- 适合跨服务协调
缺点:
- 复杂度高(消息丢失、重复、顺序)
- 延迟增加
- 调试困难
适用场景:
- 跨服务事件通知
- 最终一致性场景
- 长事务编排选型建议:
查询用同步,操作用异步
具体:
- 查询服务状态 → HTTP/gRPC
- 下单操作 → 异步(消息队列)
- 通知其他服务 → 异步(领域事件)
- 短时间操作 → 同步
- 跨服务协调 → 异步三、分布式事务与数据一致性
微服务拆分后,最大的问题是数据一致性
传统单体:一个数据库,ACID 事务
微服务:多个数据库,不能跨服务事务
解决思路:不用分布式事务,用最终一致性1. 最终一致性(Eventual Consistency)
最常用的方案
流程:
1. 服务 A 执行本地事务 + 发事件
2. 服务 B 收到事件,执行本地事务
3. 如果 B 失败,重试或补偿
示例:
下单 → 订单服务保存订单 + 发"订单已创建"事件
库存服务收到事件 → 扣库存
支付服务收到事件 → 发起支付
优点:简单,可靠
缺点:数据有短暂不一致(秒级)
适合:大部分业务场景2. Saga 模式
Saga 把长事务拆成多个本地事务,每个事务有补偿操作
两种实现方式:
1. 编排(Choreography):每个服务监听事件,执行自己的操作
2. 协调(Orchestration):一个协调器编排所有操作
示例(订单 Saga):
1. 订单服务:创建订单(待支付)
2. 支付服务:扣款
3. 库存服务:扣库存
4. 物流服务:创建配送
如果第 3 步失败:
补偿第 2 步:退款
补偿第 1 步:取消订单
编排 vs 协调:
编排:服务间通过事件通信,松耦合
协调:协调器控制流程,紧耦合但可控
→ 推荐编排,更灵活3. TCC(Try-Confirm-Cancel)
TCC 是两阶段事务的变体
Try:预留资源(冻结库存、冻结余额)
Confirm:确认使用(扣库存、扣款)
Cancel:释放资源(解冻库存、退款)
示例:
Try:订单服务冻结库存、支付服务冻结余额
Confirm:扣库存、扣款
Cancel:解冻库存、退款
优点:强一致性
缺点:实现复杂,每个服务都要实现 Try/Confirm/Cancel
适合:资金相关、库存敏感场景选型建议:
| 场景 | 推荐方案 |
|---|---|
| 大部分业务 | 最终一致性 + 事件 |
| 长事务,需要补偿 | Saga 编排 |
| 资金敏感,强一致性 | TCC |
| 简单场景 | 本地事务 + 重试 |
四、拆分策略
拆分时机
什么时候不该拆:
- 业务不确定,还在快速迭代
- 团队规模小(< 10 人)
- 业务逻辑简单,单体够用
什么时候该拆:
- 单体编译/部署慢(> 10 分钟)
- 团队规模大(> 30 人),协作困难
- 某个模块需要独立扩缩容
- 需要技术栈隔离拆分顺序
先拆与核心业务无关的辅助服务
日志、通知、文件存储 → 先拆
再拆核心业务中边界清晰的
用户、权限 → 边界清晰,容易拆
最后拆核心业务中耦合深的
订单、支付 → 耦合深,最后拆
原则:先易后难,逐步拆分五、微服务常见坑
| 坑 | 后果 | 对策 |
|---|---|---|
| 拆分粒度太细 | 服务太多,运维成本高 | 一个团队 2-3 个服务 |
| 共享数据库 | 服务耦合,改了影响别的 | 每个服务独立数据库 |
| 分布式事务 | 复杂度高,性能差 | 用最终一致性 + Saga |
| 服务间循环调用 | 依赖复杂,难定位问题 | 分层调用,避免循环 |
| 不加限流/熔断 | 雪崩效应 | 限流、熔断、降级 |
| 过度设计 | 微服务比单体还慢 | 先单体,再按需拆分 |
相关与延伸
下一篇:DDD 领域驱动设计——通用语言、聚合、实体、值对象、战术与战略设计;分层架构,见 分层架构——整洁架构、六边形架构。
一句话总结
微服务拆分:按限界上下文拆分,每个服务独立数据库;服务间通信查询用同步(HTTP/gRPC),操作用异步(消息队列);数据一致性不用分布式事务,用最终一致性 + 事件(适合大部分场景)、Saga 编排(长事务需要补偿)、TCC(资金敏感强一致性);拆分时机:单体编译慢、团队大、需要独立扩缩容;拆分顺序:先易后难,先辅助服务最后核心业务;原则:一个团队 2-3 个服务,先单体再按需拆分,不要过度设计。