ccb1900 / blog

blog
https://blog.itiswho.com
MIT License
1 stars 0 forks source link

微服务中事件驱动的数据管理 #51

Open ccb1900 opened 5 years ago

ccb1900 commented 5 years ago

微服务和分布式数据管理的问题

典型的单体应用有一个关系数据库。使用关系数据库的一个好处就是可以在应用中使用ACID事务,这在以下几个方面提供了重要的保障:

因此,你的应用可以简单的开始一个事务,改变很多行数据,然后提交。 关系型数据库都可以用sql查询,所有的数据都在同一个数据库,查询也比较方便。

不幸的是,在微服务架构中,数据访问变得很复杂。这是因为每个微服务的数据是私有的,只能通过它提供的api访问。封装数据可以保证微服务是松散耦合的,可以独立演进。如果多个服务访问相同的数据,则架构更新需要对所有服务进行耗时,协调的更新。

更糟糕的是,不同的微服务经常使用不同种类的数据库,现代应用程序存储和处理各种数据,关系数据库并不总是最佳选择。某下情况下,NoSQL数据库可能具有更方便的数据模型,并提供更好的性能和可伸缩性。例如,存储和查询文本的服务使用文本搜索引擎(如Elasticsearch)是有意义的。同样,存储社交图数据的服务应该使用图形数据库,例如Neo4j。所以,基于微服务的应用程序通常使用SQL和NoSQL数据库的混合,即所谓的多语言持久性方法。

用于数据存储的分区多字节持久架构具有许多优点,松散耦合的服务以及更好的性能和可扩展性。然而,这带来了一些分布式数据管理的挑战。

第一个挑战是如何实现维护多个服务之间一致性的业务事务。 第二个挑战是如何实现从多个服务检索数据的查询。

事件驱动架构

很多应用中使用了事件驱动架构。

在这个架构中,当一些值得注意的事情发生时,微服务会发布一个事件。其他微服务订阅了这些事件。当微服务接收事件时,它可以更新自己的业务实体,这可能导致发布更多事件。

  1. 订单服务创建状态为NEW的订单并发布订单创建事件。 image
  2. 客户服务部门使用订单创建事件,保留订单信用,并发布信用保留事件。 image
  3. Order Service使用Credit Reserved事件,并将订单状态更改为OPEN image

更复杂的情况可能涉及其他步骤,例如在检查客户信用的同时预订库存。

a. 每个服务以原子方式更新数据库并发布事件。 b. Message Broker保证事件至少传递一次,然后您可以实现跨多个服务的业务事务。

值得注意的是,这并不是ACID事务。它们提供了许多较弱的保证,例如最终的一致性。此事务模型称为BASE模型(http://queue.acm.org/detail.cfm?id=1394128)。

可以使用事件维护一个物化视图。

  1. 它支持跨多个服务的事务的实现,并提供最终的一致性
  2. 它还使应用程序能够维护物化视图
  3. 缺点:相比较ACID事务模型,这种模型编程更复杂。
  4. 缺点:您必须实现补偿事务以从应用程序级故障中恢复
  5. 缺点:应用程序必须处理不一致的数据
  6. 缺点:订阅者必须检测并忽略重复事件

实现原子性

使用本地事务发布事件

挖掘数据库事务日志

使用事件源(此方法为常用方法)

事件源通过使用完全不同的,以事件为中心的方法来保持业务实体,从而在没有2PC的情况下实现原子性。应用程序存储一系列状态改变事件,而不是存储实体的当前状态。应用程序通过重放事件来重建实体的当前状态。每当业务实体的状态发生变化时,都会在事件列表中附加一个新事件。由于保存事件是单个操作,因此它本质上是原子的。但是,在使用事件源时,订单服务会以状态更改事件的形式存储订单:已创建,已批准,已发货,已取消。每个事件都包含足够的数据来重建订单的状态。 image

事件在事件store中持续存在,事件store是事件的数据库。store中有一个用于添加和检索实体事件的API。事件store的行为类似于我们在前面的架构中描述的message broker。它提供了一个API,使服务可以订阅事件。事件 Store向所有感兴趣的订阅者提供所有事件。事件Store是事件驱动的微服务架构的支柱。

事件源的优先

参考

分布式事务-两段式提交

原文链接

CAP定理