工作中使用了微服务架构,接下来的一段时间里,我会写一系列的文章来介绍微服务架构,这篇文章主要讲述了微服务架构中的数据管理。
翻译和整理自:
- http://microservices.io/patterns/data/database-per-service.html
- http://microservices.io/patterns/data/shared-database.html
- http://microservices.io/patterns/data/event-driven-architecture.html
- http://microservices.io/patterns/data/event-sourcing.html
- http://microservices.io/patterns/data/transaction-log-tailing.html
- http://microservices.io/patterns/data/database-triggers.html
- http://microservices.io/patterns/data/application-events.html
- http://microservices.io/patterns/data/cqrs.html
- http://www.cnblogs.com/dinglang/p/5679542.html (文中摘抄了这篇博文的大部分内容)
一、事件驱动架构
1.上下文和问题
你已经应用了
Database per Service 模式。每个服务都有它自己的数据库。但是,有一些业务事务跨越多个服务,所以你需要一种机制来确保多个服务之间的数据一致性。比如说,假设你在构建一个在线商城,应用必须保证一个新订单的数额不超过客户的余额。因为订单和客户在不同的数据库之间,所以你不能简单的用本地的ACID事务去达到这个目的。那么,怎么保障数据的一致性呢?
强制条件: 不使用两阶段提交协议 (译者注: 读者如果不了解分布式事务,可以参考下这篇文章: http://www.cnblogs.com/dinglang/p/5679542.html)
2.解决方案
使用一个数据驱动的,最终一致性的解决方案。每个服务在更新数据时会发布一个事件,别的服务订阅这些事件,当收到事件时,服务更新自己的数据。
示例:
- Order Service 创建一个处于待定状态的订单,然后发布一个OrderCreated 事件。
- Customer Service 收到这个事件,判断用户的余额满不满足这个订单的需求。然后它发布一个 Credit Reserve 事件或者一个 CreditLimitExceeded 事件。
- Order Service 收到了 Customer Service 发布的时间,把订单的状态改成通过或取消。
3.结果
优点:
- 应用不需要使用分布式事务就能维持多个服务之间的数据一致性
缺点:
- 编程模型更复杂了
要解决的问题:
- 为了实现可靠性,应用必须原子的更新自己的数据库和发布事件。它不能使用传统的分布式事务的机制来拓展到数据库和消息代理的层面,而必须使用如下的模式中的一种,来原子的更新状态和发布事件:
二、事件源(Event sourcing)
1.上下文和问题
你已经应用了上文的事件驱动架构模式。为了实现可靠性,应用必须原子的更新自己的数据库和发布事件。使用分布式事务来覆盖数据库和消息代理层面不可行的,那么怎么做呢?
2.解决方案
解决这个问题的一个好方案是使用事件源。事件源把业务实体比如订单和客户持久化成一系列状态变化的事件。当一个业务实体的状态变化时,新的事件加入到这个事件列表的尾端。因为保存一个事件是单个操作,它是原子性的。应用可以通过重现这些事件的方式来重新构建一个实体现在的状态。
应用把事件持久化在一个事件存储中,它是一个事件的数据库。这个存储有一个增加和获取事件的api。这个事件存储也类似于一个消息代理,它提供了一个api让服务可以订阅事件。当一个服务把事件保存在事件存储中时,这个事件被传递到所有的订阅者那。
有一些实体,比如说客户,可能会有很大数量的事件。为了优化负载量,应用可以周期性地保存一个实体当前状态的快照。为了重新构建当前的状态,应用找到最新的快照和那个快照之后的事件,于是需要重现的事件就少了一点。
示例
Customers and Orders 是一个使用事件源和 CQRS的示例应用。这个应用使用Java语言编写,用到了Spring Boot。它使用 Eventuate构建, 这是一个基于事件源和CQRS的应用平台。下图展示了它是怎么持久化订单的:
应用以一系列事件的方式持久化
Order ,而不是简单地把每个order当前的状态保存在表中。
CustomerService可以订阅order events,然后更新自己的状态。
Order:
public class Order extends ReflectiveMutableCommandProcessingAggregate<Order, OrderCommand> {
private OrderState state;
private String customerId;
public OrderState getState() {