跳转到内容

数据所有权与去共享库

用途:微服务落地时最难的一步——数据边界怎么划、怎么禁止跨服务读表

多数“伪微服务”的真实形态是:服务拆了,数据库没拆。多个服务读写同一张表,于是:

  • 任何字段变更都是跨团队破坏性变更;
  • 业务规则散在各服务的 SQL 里,无法集中演进;
  • 无法独立部署与独立扩容(数据库成为共享状态);
  • 一致性靠“大家都小心点”维持。

数据所有权原则:每张表只有一个写入方(owner 服务),其他方只能通过 owner 暴露的接口或事件获取数据。

需求 方案 注意点
其他服务需要查询 owner 的数据 API 查询 / 事件订阅本地副本 副本允许延迟,需要版本与失效策略
跨服务聚合查询(列表页要展示多方字段) BFF/查询服务并行调用;或建投影/宽表;或同步到搜索引擎 避免串行调用链过长;注意部分失败降级
报表与分析 数据仓库/湖,从各服务库抽取 不要为了报表开放生产库直连
强一致跨表事务 归入同一 owner 服务,或改用同库不同 schema 跨服务强一致是反模式信号
历史数据迁移 双写 + 回填 + 校验 + 切读 + 停写 每阶段都要有对账与回滚开关
  1. 权限层面:数据库账号按服务隔离,非 owner 无写权限(甚至无读权限)。
  2. 架构测试:禁止 import 其他模块的持久层类。
  3. 网关/服务网格:数据库访问走 sidecar 或代理,可审计来源。
  4. 代码评审清单:新增 SQL 必须回答“这张表的 owner 是谁”。

订阅 owner 的事件在本地维护只读副本,是消除同步依赖的常用做法:

  • 副本表结构面向本地查询需求设计,不必与源一致;
  • 必须处理乱序与重复(版本号 + 幂等写入);
  • 需要初始化路径(快照 + 增量)与重建能力;
  • 明确可接受延迟,并在 UI 上体现“数据可能滞后”。
误区 修正
拆服务不拆库 数据未隔离时,服务拆分只是形式
共享只读库当“解耦” 只读也造成 schema 耦合,变更仍会破坏下游
每个服务各自缓存一份全量数据 无失效策略的副本比共享库更危险
用分布式锁掩盖数据归属问题 回到 owner 与事件模型
迁移期间长期双写无退出计划 设定切读与停写时间点,并对账验证
  • Sam Newman《Building Microservices》第 5 章(数据库集成)
  • Chris Richardson《微服务架构设计模式》第 5 章(Saga 与数据一致性)
  • Martin Fowler 关于 Database Per Service 模式的论述