3、服务拆分原则与策略

聊到微服务拆分,很多人第一反应就是「按功能拆呗」。嗯,这话没错,但太笼统了。我在实际项目中见过太多拆分失败的案例——要么拆得太碎,一个订单服务拆成十几个,结果改个需求要协调七八个团队;要么拆得太粗,本质上还是单体,只不过换了个马甲。

这一章,我就把服务拆分的核心原则和策略掰开揉碎讲清楚。尤其是库存系统,它天生就是个「高耦合」的业务模块,怎么拆才合理?我们一步步来看。

3.1 微服务拆分的两大原则

3.1.1 高内聚低耦合

说白了,就是把关系紧密的功能放在同一个服务里,服务之间尽量少通信。你想想看,如果两个功能频繁互相调用,那它们就不该被拆开。

高内聚:一个服务内部的各个模块,应该围绕同一个业务目标。比如库存服务里的「入库」、「出库」、「库存查询」,它们都围绕「库存数量」这个核心概念。

低耦合:服务之间的依赖要轻。接口要稳定,数据模型要独立。我见过一个项目,订单服务直接读取库存服务的数据库表——这哪是微服务?这是分布式单体。

核心判断标准:如果两个功能模块之间的调用频率,远高于它们与外部模块的调用频率,那它们就应该放在同一个服务里。

3.1.2 单一职责

这个原则来自面向对象设计,但在微服务里同样适用。一个服务只做一件事,并且把它做好。

举个例子:库存服务只负责库存数量的增减和查询。它不应该管订单的支付状态,也不应该管商品的定价。一旦你让库存服务去处理「订单支付成功后才扣减库存」的逻辑,那这个服务就变脏了。

我个人习惯用「业务动词」来检验单一职责。一个服务对外暴露的接口,动词应该高度一致。比如库存服务:reserve()release()queryStock()。如果出现 createOrder()calculatePrice(),那就要警惕了。

避坑指南:我曾经接手过一个「库存服务」,里面居然有用户积分查询的接口。原因是开发图省事,觉得「反正都是查数据」。结果后来积分规则变了,改库存服务的人完全不懂积分业务,差点出生产事故。

3.2 拆分策略:两种主流方法

3.2.1 按业务能力拆分

这是最直观的方式。看业务系统有哪些核心能力,每个能力对应一个服务。

拿电商系统举例:

  • 商品服务:商品信息、分类、属性
  • 订单服务:订单创建、状态流转
  • 库存服务:库存管理、出入库
  • 支付服务:支付、退款
  • 用户服务:用户信息、地址

这种拆分方式的好处是直观,业务人员也能理解。但问题在于,业务能力之间的边界有时候很模糊。比如「预售」功能,它既涉及商品,又涉及库存,还涉及订单。你把它放哪?

3.2.2 按子域拆分(DDD 方式)

这是更精细的做法。先做领域建模,识别出核心域、支撑域、通用域,然后按限界上下文来拆分。

库存系统在 DDD 里通常属于支撑域。它不直接产生订单,但没有它订单也跑不起来。它的限界上下文很清晰:库存聚合根、库存流水、库存预警。

我建议的做法是:先用业务能力拆分做一个粗粒度的划分,再用 DDD 的子域分析来验证和调整。不要一上来就搞 DDD,容易陷入过度建模。

注意:按子域拆分时,要警惕「共享内核」陷阱。两个服务如果共享同一个领域模型,那它们其实是一个服务。我见过有人把「库存」和「仓储」拆成两个服务,结果每次查询都要跨服务 join,性能惨不忍睹。

3.3 库存系统服务粒度评估

好,理论讲完了。我们拿库存系统来实战一下。假设我们要设计一个库存微服务,怎么判断粒度是否合理?

我总结了四个评估维度:

评估维度 说明 库存系统示例
业务完整性 服务是否覆盖一个完整的业务场景 库存服务应包含:库存查询、预占、释放、实际扣减
数据独立性 服务是否拥有独立的数据库 库存数据不应与订单数据混在一个库
变更频率 服务内部模块的变更频率是否一致 库存预警逻辑经常变,但基础库存查询很少变——是否要拆开?
团队规模 一个服务是否只需要一个小团队维护 库存服务通常 2-3 人维护即可,拆太细反而增加沟通成本

这里有个常见的纠结:库存预占和库存实际扣减,要不要拆成两个服务?

我的答案是:不要拆。为什么呢?

  • 预占和扣减操作的是同一批数据(库存数量)
  • 它们的事务一致性要求极高——预占了没扣减,库存就虚高了;扣减了没预占,库存就负数了
  • 拆成两个服务,你就得引入分布式事务,复杂度飙升

你看,这就是用「数据独立性」和「业务完整性」两个维度交叉验证的结果。

我的经验:库存系统的拆分,宁可粗一点,不要细一点。因为库存是强一致性的业务,拆得太细,分布式事务会让你痛不欲生。我见过一个团队把「库存查询」和「库存扣减」拆成两个服务,结果每次扣减前都要调查询接口做校验,网络延迟一高就出问题。

最后,我画了一张图,把服务拆分的核心逻辑串起来。你可以把它当作一个决策流程:

库存系统服务拆分决策流程 第一步:识别业务能力 商品、订单、库存、支付、用户 第二步:子域分析(DDD) 核心域 / 支撑域 / 通用域 第三步:服务粒度评估 业务完整性 / 数据独立性 / 变更频率 / 团队规模 第四步:确定服务边界 输出:服务划分文档 + 接口契约 库存系统关键点 • 库存是强一致性业务 • 预占与扣减不要拆 • 独立数据库 • 2-3人维护一个服务 • 避免分布式事务 • 接口要稳定 • 数据模型独立 • 变更频率要一致 • 宁可粗不要细 • 先业务能力后DDD • 避免共享内核 • 用业务动词检验

嗯,这一章的内容就到这里。服务拆分没有银弹,但掌握了原则和策略,至少不会走偏。下一章我们会深入库存系统的数据模型设计,看看怎么在微服务架构下保证数据一致性。

一句话总结:高内聚低耦合是目标,单一职责是手段。库存系统拆分时,多想想「这个功能真的需要独立部署吗?」——答案往往是否定的。

公众号:蓝海资料掘金营,微信deep3321