微服务为什么强调每个服务拥有自己的数据?
简化版
微服务强调服务拥有自己的数据,是为了保证业务规则、数据写入和演进边界一致。其他服务不能绕过接口直接改表,否则会破坏封装,导致服务无法独立发布和独立演进。
详细版
“每个服务拥有自己的数据”不一定等于每个服务必须独占一个物理数据库实例,而是强调数据所有权:某类核心数据只能由所属服务负责写入和维护,其他服务通过 API、领域事件、数据同步视图等方式访问。
好处包括:
- 服务内部可以独立修改表结构。
- 业务规则集中在数据 owner 服务中。
- 避免多个服务直接写同一张表造成数据异常。
- 服务发布和扩容更独立。
- 更容易划分故障责任和数据责任。
代价是跨服务查询、跨服务事务和数据一致性会变复杂,需要通过接口聚合、CQRS、事件驱动、最终一致、数据冗余等方式解决。
完整版教学
一、数据所有权到底是什么意思
微服务里的数据所有权,可以理解为“谁负责解释和改变这份数据”。
比如订单状态不是一个普通字段,它背后有业务规则:待支付、已支付、已取消、已发货、退款中,每个状态之间能不能流转都有约束。如果客服服务、营销服务、财务服务都能直接改订单表,那么订单状态机就被绕开了。
所以订单数据应该由订单服务拥有。其他服务想取消订单、查询订单、订阅订单变化,都应该通过订单服务提供的能力完成。
二、为什么共享数据库会破坏微服务
共享数据库短期很省事,长期很难维护。
假设多个服务共用一张用户表:
用户服务:维护手机号、登录密码
订单服务:读取用户等级
营销服务:写入用户标签
风控服务:更新风险状态
看起来大家都很方便,但问题会很快出现。用户服务改手机号字段格式,营销服务可能解析失败;风控服务更新状态时没有经过用户服务校验,可能产生非法状态;某个服务慢 SQL 把整库拖慢,所有服务一起受影响。
共享数据库会让服务之间形成隐形依赖,代码上看不到,数据库表上全都绑在一起。
三、一个服务一个库是不是硬要求
面试里要讲清楚:逻辑数据所有权比物理数据库实例更重要。
在早期阶段,多个服务可以共用一个数据库实例,但要做到:
- 每个服务只写自己的表。
- 不跨服务直接访问内部表。
- 表结构变更由数据 owner 服务负责。
- 其他服务通过接口或事件拿数据。
成熟后,可以进一步演进为每个服务独立 schema、独立数据库实例,甚至使用不同存储。比如订单用 MySQL,搜索用 Elasticsearch,日志用 ClickHouse。
四、跨服务查询怎么办
数据归属清晰后,跨服务查询会变麻烦,这是微服务必须面对的代价。
例如订单列表要展示用户昵称、商品名称、支付状态。不能让订单服务直接 join 用户表和商品表,常见做法有三种:
| 做法 | 适用场景 | 注意点 |
|---|---|---|
| API 聚合 | 实时性要求较高、数据量不大 | 注意调用延迟和降级 |
| 数据冗余快照 | 下单时保存用户昵称、商品名称 | 快照不随原数据变化 |
| 异步同步读模型 | 报表、搜索、列表页 | 接受最终一致 |
例如订单详情页可以调用用户服务拿最新昵称;订单历史列表可以用下单时的用户昵称快照;运营报表可以由消息同步到宽表。
五、跨服务事务怎么办
如果每个服务都有自己的数据,本地事务就不能跨服务覆盖。解决思路不是回到共享数据库,而是根据场景选择一致性方案。
核心强一致场景可以谨慎使用 TCC 或本地预留资源;大多数业务副作用可以用可靠消息和补偿实现最终一致;周期性对账可以兜底修复异常。
比如支付成功后更新订单状态和增加积分,订单状态是核心链路,积分可以通过支付成功事件异步处理。如果积分失败,重试和补偿即可,不一定要让支付失败。
六、常见误区与追问
这道题要紧扣「每服务独立数据库」本身回答,不能把它混成泛泛的微服务架构套话。面试官通常会沿着“为什么需要、流程怎么走、失败怎么兜、代价是什么”继续追问,所以回答要覆盖服务边界、通信方式、网关/BFF、数据归属、版本兼容和部署治理。
| 回答层次 | 要讲清的内容 | 容易漏掉的边界 |
|---|---|---|
| 核心结论 | 每个微服务拥有自己的数据,其他服务只能通过 API 或事件访问,避免数据库层强耦合 | 不要停在名词解释 |
| 流程机制 | 按服务划分数据所有权 -> 禁止跨服务直连数据库 -> 通过 API 查询命令 -> 用事件同步读模型 -> 处理最终一致 -> 对账补偿异常 | 要说清触发点、状态变化、确认点和失败兜底 |
| 工程取舍 | 订单服务不能直接改库存库表,应通过库存服务 API 或库存事件协作,否则服务边界形同虚设 | 微服务提升团队自治和独立演进能力,但会带来分布式调用、数据一致性、依赖治理和运维复杂度 |
每服务独立数据库 面试拆解:
1. 按服务划分数据所有权
2. 禁止跨服务直连数据库
3. 通过 API 查询命令
4. 用事件同步读模型
5. 处理最终一致
6. 对账补偿异常
记忆钩子:先给结论,再拆流程,再讲数字例子和失败边界;回答「每服务独立数据库」时要围绕题目问法收束,不要把相邻概念堆成一段没有重点的名词清单。
- 误区:微服务可以共享一个数据库只要表分开。 共享库会导致发布、权限、模型和性能耦合。
- 误区:独立数据库必须物理独立实例。 核心是数据所有权隔离,物理形态可按阶段演进。
- 误区:不能 Join 就没法查数据。 可以用 API 聚合、读模型、事件同步和搜索/OLAP 承接。
- 追问:跨服务事务怎么办? 用 Saga、TCC、可靠消息、补偿和最终一致设计。
- 追问:报表查询怎么做? 同步到数仓、宽表、搜索或专门读模型。
- 追问:如何避免数据重复混乱? 明确主数据归属、事件版本和对账规则。
七、加强记忆
微服务的数据原则不是“每个服务必须买一台数据库”,而是“数据的写入权和业务解释权必须归属于一个服务”。只要其他服务能绕过 owner 直接改表,服务边界就会被打穿,微服务就会慢慢退化成分布式单体。