1. 数据库设计的核心问题

微服务架构近年来持续发展,相较于传统的单体架构,它带来了诸多优势。然而,微服务架构也带来了新的挑战,尤其是在数据管理方面。

微服务中数据库设计的两个核心问题是:

  • 数据如何组织?
  • 数据应该存储在哪里?

本文将围绕这两个问题展开讨论。

2. 每个服务独立数据库(Database per Service)

在微服务架构中,常见的数据库组织方式有两种:

  1. 每个服务一个数据库(Database per Service)
  2. 多个服务共享数据库(Shared Database)

我们先来分析第一种方式。

2.1. 基本概念

微服务的核心特性是松耦合、可扩展、独立开发和部署。每个服务拥有自己的数据库正是符合这些特性的最佳实践。如下图所示:

Blank diagram 1

每个微服务拥有自己的数据存储(可以是独立的数据库、schema 或表),其他服务不能直接访问该数据存储。这种方式带来了以下优势:

松耦合:各服务数据库相互隔离,修改一个服务的数据库结构不会影响其他服务
高可用性:避免了单点故障,提升了系统整体的容错能力
易扩展:可以根据服务的负载情况独立扩展数据库
领域封装:服务与其数据紧密结合,有利于领域模型的理解和维护
多语言持久化(Polyglot Persistence):可以根据服务需求选择最适合的数据库类型,如 SQL、NoSQL 等

2.2. 潜在问题

虽然优点众多,但这种方式也带来了一些挑战:

跨服务数据访问复杂:服务之间无法直接访问对方数据库,必须通过 API 或事件机制通信
事务一致性难保证:分布式事务难以实现,ACID 特性无法跨服务保持
调试复杂度高:数据分布在多个服务中,问题排查和日志追踪更复杂
需要容错机制:服务调用失败时需有补偿机制,如重试、回滚、熔断等(例如 Hystrix)

例如,服务 A 调用服务 B 的接口进行支付操作,如果服务 B 不可用,A 需要等待或进行补偿处理。此时,熔断器(Circuit Breaker) 模式可以有效缓解这类问题。


3. 共享数据库(Shared Database)

共享数据库是一种反模式(anti-pattern),但有时也有其适用场景。

3.1. 基本概念

多个服务共享同一个数据库,如下图所示:

Blank diagram

虽然这种方式简化了事务管理,但同时也带来了以下问题:

紧耦合:服务之间共享数据库,修改表结构可能影响多个服务
扩展性差:数据库成为瓶颈,限制了服务的横向扩展
部署复杂:多个服务依赖同一个数据库,部署和维护成本高
数据一致性风险:多个服务写入同一张表,容易出现并发冲突

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 等模式可以帮助我们更好地应对分布式数据管理的挑战。

最终,数据库选型应结合实际业务场景,权衡性能、一致性、可扩展性等多个维度,选择最适合当前服务的技术栈。


附:推荐阅读


原始标题:Database Design in a Microservices Architecture