3. 基于领域边界的数据库拆分原则
在微服务架构中,数据库不再是单一的数据孤岛,而是每个限界上下文(Bounded Context)的私有持久化边界。错误的数据库拆分会导致跨服务查询爆炸、分布式事务蔓延,最终使系统退化回单体耦合状态。本章围绕“限界上下文”这一核心,给出数据库拆分的具体原则、策略以及事务边界与一致性模型的选择依据。
3.1 根据限界上下文划分数据库
限界上下文是领域驱动设计(DDD)中定义模型边界的核心模式。每个限界上下文拥有独立的业务语言、业务规则和数据模型。数据库拆分的第一原则就是:一个限界上下文对应一个独立的数据库实例(或 Schema)。
| 限界上下文 | 业务职责 | 数据库归属 | 数据访问模式 |
|---|---|---|---|
| 用户上下文 | 注册、登录、权限 | user_db | 高读、低写、缓存优先 |
| 订单上下文 | 下单、支付、退款 | order_db | 高写、事务强一致 |
| 库存上下文 | 库存扣减、补货 | inventory_db | 高并发写、乐观锁 |
| 商品上下文 | 商品信息、分类、搜索 | product_db | 高读、写少、ES 辅助 |
| 支付上下文 | 支付渠道、对账 | payment_db | 最终一致性、异步 |
实践要点:不要因为“数据关联查询方便”而合并两个限界上下文的数据库。跨上下文的数据查询应通过 API 编排或 CQRS 模式解决,而非数据库 JOIN。
3.2 数据库拆分策略
根据业务规模和数据量级,数据库拆分可分为三个层次:单库、分库、分表。选择哪种策略取决于数据量、并发量以及业务增长预期。
3.2.1 单库模式
适用于小型项目或早期阶段。一个限界上下文对应一个数据库实例,内部使用多张表组织数据。优点是架构简单、事务支持完整;缺点是单库存在性能上限,无法水平扩展。
3.2.2 分库模式
当单库无法满足并发或存储需求时,将一个限界上下文的数据水平拆分到多个数据库实例中。分库键(Sharding Key)的选择至关重要,通常使用用户 ID、订单 ID 等业务主键。
3.2.3 分表模式
当单表数据量过大(如超过千万行)时,将一张表按时间、哈希或范围拆分为多张物理表。分表通常与分库组合使用,形成“分库分表”方案。
| 拆分策略 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 单库 | 数据量 < 100GB,QPS < 2000 | 事务完整、开发简单 | 无法水平扩展 |
| 分库 | 数据量 > 100GB,QPS > 5000 | 水平扩展、隔离性好 | 跨库查询复杂、分布式事务 |
| 分表 | 单表行数 > 1000 万 | 降低单表压力、提升查询性能 | 跨表聚合查询困难 |
| 分库+分表 | 海量数据 + 超高并发 | 极致扩展能力 | 运维复杂、路由逻辑重 |
避坑提示:不要过早引入分库分表。在单库模式下通过索引优化、缓存、读写分离等手段通常能支撑千万级日活。分库分表带来的分布式事务和查询复杂度,往往比性能收益更早成为瓶颈。
3.3 事务边界与一致性模型
数据库拆分后,事务边界从单库本地事务变为跨库分布式事务。一致性模型的选择直接影响系统可用性和数据正确性。
3.3.1 事务边界划分原则
- 强一致性事务:仅在一个限界上下文内部使用,通过本地 ACID 事务保证。
- 最终一致性事务:跨限界上下文的操作,通过 Saga、事件驱动或 TCC 模式实现。
- 事务边界与聚合根对齐:一个事务只修改一个聚合根,避免跨聚合的事务。
3.3.2 一致性模型对比
| 一致性模型 | 适用场景 | 实现方式 | 性能影响 |
|---|---|---|---|
| 强一致性 | 单库、单聚合根操作 | 本地事务(ACID) | 低 |
| 最终一致性 | 跨上下文、异步操作 | 事件驱动 + 补偿 | 中 |
| 弱一致性 | 读多写少、可容忍延迟 | 缓存 + 异步同步 | 高 |
| 可串行化快照隔离 | 高并发写、冲突少 | 乐观锁 + 重试 | 中高 |
Go 微服务实践建议:在 Go 中实现 Saga 模式时,优先使用
github.com/uber-go/cadence 或 github.com/ThreeDotsLabs/watermill 等成熟框架,避免手写分布式事务协调逻辑。每个 Saga 步骤应幂等,补偿操作必须可重入。
3.3.3 一致性模型选择矩阵
根据业务对一致性的容忍度,选择合适模型:
- 资金类操作(支付、转账):强一致性或 Saga 严格顺序执行。
- 库存扣减:最终一致性 + 乐观锁,允许超卖后补偿。
- 用户资料更新:最终一致性,缓存异步刷新。
- 日志/审计:弱一致性,批量写入。
关键提醒:不要试图用分布式事务模拟单库 ACID。跨库的 2PC(两阶段提交)在微服务环境中几乎不可用,因为它会阻塞资源、降低可用性。Saga 模式才是跨限界上下文事务的正确选择。
3.4 本章小结
基于领域边界的数据库拆分,核心在于“限界上下文即数据库边界”。拆分策略从单库到分库分表逐级演进,事务边界与一致性模型的选择必须与业务容忍度对齐。记住三条铁律:
- 一个限界上下文一个数据库,禁止跨上下文直接访问。
- 拆分策略按需演进,不要为未来过度设计。
- 事务边界与聚合根对齐,跨上下文用 Saga 保证最终一致性。