4、服务拆分方法论:按业务域拆分、按功能拆分、拆分粒度的把控,以及我踩过的拆分过细的坑
服务拆分,说白了就是「把一个大系统切碎」。
但怎么切?切多大?切完怎么粘回去?
这三个问题,我花了整整三年才想明白。今天我把这些经验掰开揉碎讲给你听。
4.1 按业务域拆分:最自然的切法
我个人习惯,拿到一个系统先画业务域地图。
什么是业务域?就是一组紧密相关的业务能力。比如电商系统,天然就有:
- 用户域:注册、登录、权限
- 商品域:SPU、SKU、库存
- 订单域:下单、支付、退款
- 营销域:优惠券、活动、积分
每个域内部高内聚,域之间低耦合。这就是拆分的黄金法则。
核心原则:一个业务域的变化,不应该影响其他域。
我在项目中遇到过最典型的案例:某电商平台把「商品评价」和「商品详情」拆成了两个服务。结果每次改评价展示逻辑,都要同时改两个服务。为什么?因为评价和详情本质上属于同一个业务域——商品域。
你想想看,评价数据是商品的一部分,展示评价也是商品详情页的功能。硬拆开,反而增加了沟通成本。
4.2 按功能拆分:技术视角的切法
按功能拆分,是从技术实现角度出发的。
比如:
- 读服务:专门处理查询请求,可以做缓存优化
- 写服务:专门处理写入请求,可以做异步化
- 计算服务:专门处理复杂计算,可以独立扩缩容
- 通知服务:专门处理消息推送,可以对接多种渠道
嗯,这里要注意。按功能拆分容易陷入一个误区——过度追求「单一职责」。
我记得有一次,我们把一个订单服务拆成了:订单创建服务、订单查询服务、订单状态服务、订单日志服务。四个服务,四个数据库。结果呢?
一个简单的「创建订单」操作,需要调用三个服务:先调订单创建服务写数据,再调订单状态服务更新状态,最后调订单日志服务记录日志。如果其中一个失败,整个事务就乱了。
警告:按功能拆分时,一定要考虑事务边界。跨服务的事务,成本极高。
4.3 拆分粒度的把控:到底拆多细?
这是最考验架构师经验的地方。
我总结了一个「三问法」来判断粒度是否合适:
- 这个服务能独立部署吗?——如果不能,说明拆得太细
- 这个服务有独立的业务价值吗?——如果没有,说明拆得没必要
- 这个服务的数据能独立管理吗?——如果不能,说明边界没划对
举个例子。用户服务里有个「头像上传」功能。按功能拆分,有人会把它拆成「头像服务」。但用三问法一测:
- 能独立部署吗?能,但没必要
- 有独立业务价值吗?没有,头像只是用户属性之一
- 数据能独立管理吗?不能,头像和用户信息强关联
结论:不要拆。
我的经验:初期拆分粒度可以粗一些,等业务复杂度上来了再逐步细化。别一上来就追求「完美拆分」。
4.4 我踩过的拆分过细的坑
我曾经主导过一个项目,把系统拆成了 47 个微服务。
听起来很「先进」对吧?但实际效果惨不忍睹。
坑一:调用链爆炸
一个用户下单操作,需要调用 12 个服务。每个服务延迟 5ms,总延迟就是 60ms。再加上网络开销、序列化开销,一个接口响应时间从原来的 50ms 变成了 300ms。
坑二:数据一致性灾难
订单服务和库存服务拆开了。用户下单时,订单服务写订单,库存服务扣库存。如果库存扣成功了但订单写失败了,库存就丢了。我们不得不引入分布式事务,复杂度直接翻倍。
坑三:运维成本飙升
47 个服务,每个服务都要配置 CI/CD、监控、日志、告警。光维护这些基础设施,就占用了两个全职运维工程师。更别提服务间的依赖关系,升级一个服务要协调十几个团队。
血的教训:拆分不是目的,解决复杂度才是。如果拆分后复杂度反而增加了,那就是拆错了。
4.5 我的拆分建议
经过这些年的折腾,我总结了一套比较稳妥的拆分策略:
| 阶段 | 拆分策略 | 服务数量 |
|---|---|---|
| 初期(0-1) | 按业务域拆,每个域一个服务 | 3-5个 |
| 中期(1-10) | 按功能拆,但只拆高频变化的部分 | 8-15个 |
| 成熟期(10-100) | 按数据边界拆,每个服务拥有独立数据 | 15-30个 |
说白了,拆分是个渐进的过程。别想着一步到位。
我现在的习惯是:先按业务域拆出大块,然后观察哪些模块变化频繁、哪些模块需要独立扩缩容,再针对性地细化拆分。
一个小技巧:如果两个服务之间的调用频率超过 80%,说明它们应该合并。如果调用频率低于 20%,说明拆得合理。
最后说一句:服务拆分没有标准答案。每个系统都有自己的上下文。你想想看,一个日活 100 的系统和日活 1000 万的系统,拆分策略能一样吗?
所以,别迷信方法论,多观察自己的系统。该拆就拆,该合就合。灵活一点,比什么都强。