【微服务架构】5 数据处理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdp12315/article/details/89683669

5 数据处理

5.1 微服务中数据特征

定义微服务中的存储数据有一种方法,即从上到下方法。有业务级开始设计数据模型。如何定义数据、如何处理数据、如何与其他微服务的数据存储进行共享。

领域驱动设计实体

根据领域驱动设计,我们将会有以下几类对象:

  1. 实体 Entity
    一个不是由它的属性进行定义的对象,而是根据线程定义的。
  2. Value Object
    一个对象包含属性,但是没有概念的定义,可以被认为是不可变的。
  3. 集合 Aggregate
    一个对象的集合,由一个根entity所组织,根节点确保变化的 一致性,避免外部对象需要引用其成员。
  4. 仓库 Repository
    检索领域对象的方法应该委托给Repository对象,这样便于更换具体的存储实现的方法。

这些对象映射到我们的持久存储。领域模型(domain model)是逻辑数据模型和物理数据模型的基础。

参考:http://dddcommunity.org/resources/ddd_terms/

分离每个微服务的数据存储

每个微服务应该有自己的数据存储,这样可以与其他服务进行解耦,如下图所示。第二个服务不能直接访问第一个服务的存储层。

这样设计有以下几个理由:

  1. 如果两个微服务共享数据存储,他们将紧密耦合。改变一个微服务的数据结构,例如table,可能影响另一个微服务。如果微服务这种方式耦合,那么部署新版需要花费时间进行协调,而这是可以避免的。
    2.每个微服务应该使用最有利该服务功能的数据类型。我们不需要权衡不同服务如何选择数据库系统。每个微服务使用最合适的数据库。
    3.从性能的角度考虑,每个微服务拥有自己的数据存储,这样扩展就会很容易。数据存储可以拥有自己的服务器。

对于关系型数据库的数据存储分离可以采用以下几种方式:
1.每个微服务一个Schema
每个微服务拥有自己的schema。其他微服务可以使用相同的数据库,但是使用不同的schema。可以通过数据库访问控制机制进行约束,避免开发者直接访问其他schema。
2.每个微服务一个Database
每个微服务可以拥有自己的数据库,但是与其他微服务共享数据库服务器。不同的数据库,用户可以连接到各自的数据库,这是一种很好的分离方式。
3.每个微服务一个数据库服务器
最高度的分离,即每个微服务拥有独自的数据库服务器。当需要更高的性能时,可以采用这种方式。

在这里插入图片描述

混合持久化(Polyglot Persistence)

每个微服务应该有自己的数据存储,这意味着可以使用不同的数据存储技术。NoSQL运动导致很多新的数据存储技术产生,NoSQL可以和传统关系型数据库一起使用。根据应用需求,可以选用不同的数据存储类型来实现。在一个应用中使用多种数据存储技术,称为混合持久化。

对于某些微服务,最好用关系型数据库存储数据。其他服务,如果使用到不同的数据类型(非结构、复杂、有向图)等数据可以存储在NoSQL数据库。

https://martinfowler.com/bliki/PolyglotPersistence.html

跨微服务数据共享

某些情景下,一个微服务的客户端可能请求另一个微服务的数据。例如,一个客户端可能需要查看他的账单和以及账单状态。然后,他可能需要查询他的账户,然后到账单服务。微服务最佳实践避免将数据存在同一个数据库中。为了解决上述这个业务场景,我们可以实现一个适配服务,用于查询Account服务和Payment服务,然后将查询结果发给客户端。适配器服务也负责处理接收数据的转换,如果有需要的话。

在这里插入图片描述

改变数据会变得很复杂。在一个微服务系统中,某些业务事务横跨多个微服务。在一个零售店应用的微服务示例中,可能有一个服务用于下单,一个服务由于付款。因此,如果一个消费者用户想购买商店的某个东西时,这个业务事务可能在这两个服务中扭转。每个微服务有自己的数据存储,因此业务事务可能横跨两个或多个微服务,将调用多个数据存储。如何应对这种业务事务呢?

Event-Driven 架构

在调用涉及多个微服务的业务事务时,我们需要确保数据的一致性。可以采用分布式事务,但是有很多理由表明不应该在微服务应用中使用。主要的原因是会让微服务变得过于耦合。如果两个微服务在一个分布式事务中调用,那么其中一个错处或有性能问题,那么另一个服务也会等待直到超时发生,回滚事务。

使用事件驱动架构(Event-Driven architecture)是最好的方式来解决横跨多个微服务的业务事务。为了改变数据,第一个服务更新数据,在同一个事务中,发布一个事件。第二个微服务,订阅这个事件,当接收到这个事件时,也改变自己的数据。使用发布/订阅(publish/subscribe)通信模型,可以让两个微服务松耦合。这个耦合只存在于交互的消息中。这个技术使得微服务系统可以维护多个微服务的数据一致性,而不需要使用分布式事务。

如果微服务应用中,微服务之间发送很多消息,最好可以将这些服务合并成一个服务。但是这样可能会违背领域驱动设计的原则。横跨多个微服务的适配服务负责复杂的数据更新,可以采用事件的方式实现。

最终一致性 (Eventual Consistency)

在事件驱动的架构中,发送消息可能产生最终一致性的问题。这是君臣发生的运行时问题:服务A改变自己的数据,并发送消息到服务B,经过很短的一段时间后,服务B接收到消息,并改变自己的数据。在这个很短的接收时间里,两个服务的数据是不一致的。例如,服务A更新了订单数据,并发送消息到付款服务B,直到服务B处理完付款,有一个订单已经被付款了。当消息的接收者不能处理这个消息时会发生错误。在这个情况下,消息系统或接收消息的微服务需要解决这个问题。

由于微服务框架中每个服务拥有自己的数据库,横跨多个服务的业务事务会引入最终一致的问题。如下图所示的,可以解决这个问题。订单服务保存订单,发送操作事件。例如 OrderCreated事件 发送到Payment服务,当订单服务没有接收到Payment服务的确认消息前,订单服务处于等待状态。

付款服务(Payment)订阅OrderCreated事件,接收后处理这个事件,并在数据存储中处理付款。如果付款成功,那么将发布PaymentApproval事件,这个事件被订单服务(Order)订阅。当处理完PaymentApproval事件后,订单的状态会从等待变为批准。如果消费者查询订单的状态,他将获得两种状态中的一种:订单等待或订单完成。

在这里插入图片描述

在这种情境下,当数据不可用时,服务可以发送“对不起,请稍后重试”的消息到客户端。

数据备份

数据库系统的数据备份机制可以解决,因数据存储分离造成的数据获取问题。使用数据备份,例如,使用数据库触发器或时序的存储过程或其他进程,多个服务之间共享数据同样存在缺陷。改变一方的数据结构,将会导致备份进程的问题。这个备份机制必须能适应后续新增的服务部署。这也是一种紧耦合的形式,需要避免。

综上所述,事件驱动可以解耦两个数据存储。服务可以处理自己数据中这些事件有关的数据转换。

Event Sourcing 和CQRS(Command Query Responsibility Segregation)

在事件驱动架构中,Command Query Responsibility Segregation 和 Event Sourcing, 这两种架构模式可以结合起来解决微服务应用中的事件流。

CQRS 将数据存储分离成两个独立的部分:一部分用于读取操作,另一部分用于写操作。度操作不会改变系统的状态,只获取系统状态。写操作会改变系统的状态,但是不会返回数值。

Event Sourcing 存储一系列的事件,这些事件发生在数据改变时。

在这里插入图片描述

如上图所示,事件按顺序存储在Event stores中,数据查询模型中的数据与事件存储中的数据同步。为了让事件存储或查询模型,我们可以使用一些系统,例如 Elastic Search 来支持微服务中的查询。

这种架构可以用于处理微服务应用中的事件。

消息系统

我们可以使用消息系统或面向消息的中间件来支持事件驱动架构。

面向消息的中间件(MOM,Message-oriented Middleware),是一个软件或硬件基础设施,用于分布式系统之间发送和接收消息。MOM使得异构的应用模块分离,并降低跨多系统和网络应用开发的复杂度。中间件可以创建分布式通信层,避免开发者考虑操作系统和网络接口的细节。跨多种平台和网络的扩展,由MOM的API提供。MOM提供客户端/服务器架构模式的软件通信所需的组件,也支持异步调用。MOM减少应用开发者投入复杂的主从的客户端/服务器机制的原理。

与MOM通信可以使用不同的协议,例如

  1. AMQP(Advanced Message Queuing Protocol)
    授权管理消息提供者和客户端的行为,可以实现多个对象之间的互操作。类似SMTP、HTTP、FTP。具体实现有:RabbitMQ、Apache Qpid、Red Hat Enterprise MRG
  2. MQTT (MQ Telemetry Transport)
    MQTT是一种 发布/订阅模式,轻量级的消息协议,基于TCP/IP协议之上的。设计用于远程定位连接,带宽限制的和小编码的场景。更多在物联网IoT中使用。

分布式事务

大部分但不是全部的消息系统支持事务。当我们需要发送消息到消息系统,事务中改变数据时,也可以使用分布式事务。

分布式事务、两段提交(Two-phase commit)可以用于一个微服务,以及它的后端存储,但是不能在微服务之间使用。本质上要保持微服务的独立,因此具体的服务实例之间不应该存在密切的关系,例如两个服务之间需要两段提交。

对于跨服务的交互,事务补偿或和解逻辑应该添加以确保一致性。

猜你喜欢

转载自blog.csdn.net/gdp12315/article/details/89683669
今日推荐