1. 数据库设计的核心问题
微服务架构近年来持续发展,相较于传统的单体架构,它带来了诸多优势。然而,微服务架构也带来了新的挑战,尤其是在数据管理方面。
微服务中数据库设计的两个核心问题是:
- 数据如何组织?
- 数据应该存储在哪里?
本文将围绕这两个问题展开讨论。
2. 每个服务独立数据库(Database per Service)
在微服务架构中,常见的数据库组织方式有两种:
- 每个服务一个数据库(Database per Service)
- 多个服务共享数据库(Shared Database)
我们先来分析第一种方式。
2.1. 基本概念
微服务的核心特性是松耦合、可扩展、独立开发和部署。每个服务拥有自己的数据库正是符合这些特性的最佳实践。如下图所示:
每个微服务拥有自己的数据存储(可以是独立的数据库、schema 或表),其他服务不能直接访问该数据存储。这种方式带来了以下优势:
✅ 松耦合:各服务数据库相互隔离,修改一个服务的数据库结构不会影响其他服务
✅ 高可用性:避免了单点故障,提升了系统整体的容错能力
✅ 易扩展:可以根据服务的负载情况独立扩展数据库
✅ 领域封装:服务与其数据紧密结合,有利于领域模型的理解和维护
✅ 多语言持久化(Polyglot Persistence):可以根据服务需求选择最适合的数据库类型,如 SQL、NoSQL 等
2.2. 潜在问题
虽然优点众多,但这种方式也带来了一些挑战:
❌ 跨服务数据访问复杂:服务之间无法直接访问对方数据库,必须通过 API 或事件机制通信
❌ 事务一致性难保证:分布式事务难以实现,ACID 特性无法跨服务保持
❌ 调试复杂度高:数据分布在多个服务中,问题排查和日志追踪更复杂
❌ 需要容错机制:服务调用失败时需有补偿机制,如重试、回滚、熔断等(例如 Hystrix)
例如,服务 A 调用服务 B 的接口进行支付操作,如果服务 B 不可用,A 需要等待或进行补偿处理。此时,熔断器(Circuit Breaker) 模式可以有效缓解这类问题。
3. 共享数据库(Shared Database)
共享数据库是一种反模式(anti-pattern),但有时也有其适用场景。
3.1. 基本概念
多个服务共享同一个数据库,如下图所示:
虽然这种方式简化了事务管理,但同时也带来了以下问题:
❌ 紧耦合:服务之间共享数据库,修改表结构可能影响多个服务
❌ 扩展性差:数据库成为瓶颈,限制了服务的横向扩展
❌ 部署复杂:多个服务依赖同一个数据库,部署和维护成本高
❌ 数据一致性风险:多个服务写入同一张表,容易出现并发冲突
3.2. 适用场景
虽然不推荐,但在以下场景中可以考虑使用共享数据库:
- 正在从单体迁移到微服务架构的过渡阶段
- 有强事务一致性要求的系统
- 数据模型已经稳定,且不希望重构数据访问逻辑
4. 微服务中常见的数据管理模式
为了应对微服务架构中数据管理的挑战,业界总结出了一些经典模式。
4.1. Saga 模式(Saga Pattern)
Saga 模式用于解决跨服务的分布式事务问题。
✅ 核心思想:将一个分布式事务拆分为多个本地事务,每个服务执行本地事务后发布事件触发下一个服务的操作。
如果某个服务执行失败,则通过补偿事务来回滚前面的操作。
Saga 有两种实现方式:
- 编排式(Orchestration):由一个中央协调器(orchestrator)控制事务流程
- 协作式(Choreography):通过事件广播的方式实现服务间的协作
4.2. CQRS 模式(Command Query Responsibility Segregation)
CQRS 将写操作(Command)和读操作(Query)分离,分别使用不同的模型和数据库。
✅ 优势:
- 读写分离,提升系统性能
- 可以针对读写操作分别优化
- 降低系统复杂度,提升可维护性
通常,CQRS 会与 Event Sourcing 配合使用,以实现更强的可扩展性和数据一致性。
4.3. 事件溯源(Event Sourcing)
事件溯源是一种记录状态变化的方式。
✅ 核心思想:不直接保存当前状态,而是保存状态变化的事件。通过回放事件可以重建任意时刻的状态。
事件溯源的优点包括:
- 提供完整的审计日志
- 支持数据回滚和状态重建
- 避免对象-关系映射(ORM)中的阻抗不匹配问题
事件存储(Event Store)可以是一个数据库,也可以是一个消息中间件,所有服务都可以订阅事件并做出响应。
5. 如何选择合适的数据库技术?
在决定使用哪种数据库之前,需要考虑以下几个关键因素:
属性 | 说明 |
---|---|
✅ 读性能 | 每秒查询次数、查询响应速度 |
✅ 写性能 | 每秒写入次数、写入延迟 |
✅ 延迟 | 用户操作与数据库响应之间的延迟 |
✅ 资源效率 | CPU、内存、网络等资源消耗 |
✅ 部署效率 | 数据库对开发、部署、测试流程的影响 |
5.1. SQL vs NoSQL 对比
特性 | SQL | NoSQL |
---|---|---|
数据模型 | 关系型 | 非关系型 |
存储结构 | 表结构固定 | 支持列、文档、图、键值等多种形式 |
事务支持 | 强事务支持 | 分布式事务较弱 |
数据一致性 | 强一致性(ACID) | 最终一致性(CAP) |
横向扩展 | 困难 | 易于水平扩展 |
数据规模 | 适合中小型数据集 | 适合大数据集 |
查询能力 | 支持复杂查询 | 查询能力有限 |
数据写入方式 | 同步 | 异步 |
6. 总结
微服务架构下的数据库设计是一项复杂且关键的任务。选择每个服务独立数据库还是共享数据库,取决于业务需求、团队能力、系统规模等因素。
同时,Saga、CQRS、Event Sourcing 等模式可以帮助我们更好地应对分布式数据管理的挑战。
最终,数据库选型应结合实际业务场景,权衡性能、一致性、可扩展性等多个维度,选择最适合当前服务的技术栈。
附:推荐阅读