在微服务架构中实现查询操作有两种不同的模式:
1:API组合模式
这是最简单的方法,应尽可能使用。它的工作原理是通过定义一个API组合器(API Composer)实现查询,该API组合器会调用拥有数据的服务,并组合服务返回的查询结果
什么是API组合模式:
- API组合器
它通过查询数据提供方的服务来实现查询操作 - 数据提供方服务
拥有查询返回的部分数据的服务 - 模式:API组合
通过查询每个服务的API并组合结果,实现从多个服务检索数据的查询。
是否可以使用此模式实现特定查询操作取决几个因素,包括数据的分区方式、拥有数据的服务公开的API功能,以及服务使用数据库的功能,等等。 - API组合模式的设计缺陷:
使用此模式时,必须解决两个设计问题:
- 确定架构中的哪个组件是查询操作的API组合器
由谁来担任API组合器角色
这是必须做出的一个决定,选择由谁来扮演查询操作的API组合器角色。有以下三种方式:
1:由客户端担任API组合器
2:由实现应用程序外部的API的API Gateway来扮演API组合器的角色,用来完成查询操作和查询结果的组合。
3:将API组合器实现为独立的服务 - 如何编写有效的聚合逻辑
API组合模式的弊端:
- 增加了额外的开销
明显的缺点就是涉及多个请求和多个数据库连接 - 带来可用性降低的风险
操作的可用性随着所涉及的服务数量而下降 - 缺乏事务数据一致性
- 命令查询职责隔离(CQRS)模式
它比API组合模式更强大,但也更复杂。它维护一个或多个视图数据库(可以是NoSql也可以是关系型数据库),其唯一目的是支持查询。
为什么要使用CQRS
API组合模式是实现需要从多个服务检索数据查询的好办法。但是,它只是解决微服务架构中查询问题的不完整解决方案。因为针对一些涉及多个服务的查询,API组合无法有效地实现。
更重要的是,实现一些特定的服务查询很有挑战性。也许服务的数据库不能有效地支持查询。或者,有时必须实现检索不同服务所拥有的数据的查询。例如,Mysql对搜索支持的很差,性能低。
在微服务架构中使用API组合模式经常会遇到三个问题:
- 检索分散在多个服务中的数据会导致昂贵、低效的内存中连接
- 拥有数据的服务将数据存储在不能有效支持所需查询的数据库中
- 隔离问题意味着,拥有数据的服务不一定会实现查询操作的服务
什么是CQRS
- CQRS是命令查询职责隔离的简称,它涉及隔离或问题的隔离,它将持久化数据模型和使用数据的模块分为两部分:命令端和查询端。命令端模块和数据模型实现了创建、更新和删除操作。查询端模块和数据模型实现查询。查询端通过订阅命令端发布的事件,使其数据模型与命令端数据模型保持同步。
- 独立的查询模型可以用来处理复杂的查询场景。查询端的代码往往比命令端简单很多,因为它不需要负责实现具体的业务逻辑。查询端使用的数据库种类也很灵活,可以是NoSql,也可以是Mysql等数据库。查询端的事件处理程序会订阅领域事件并更新数据库。
- CQRS和查询专用服务
CQRS不仅可以在服务中应用,还可以使用此模式来定义查询服务。查询服务的API只包含查询操作,并无命令操作。它通过订阅由一个或多个其他服务发布的事件来确保它的数据是不断更新的,并由此实现查询操作。
在许多方面,CQRS也代表了当前流行的基于事件的数据库应用场景,例如,它可以使用关系型数据库作为记录系统,使用Elasticsearch来处理文本查询。不同之处在于CQRS使用更广泛的数据库类型,而不仅仅是一种。此外,通过订阅事件,近乎实时更新CQRS查询端的数据库。 - CQRS的好处:
1:在微服务架构中高效地实现查询
CQRS模式的一个好处是它有效地实现了检索多个服务所拥有的数据查询
2:高效地实现多种不同的查询类型
CQRS的另一个好处是它使应用程序或服务能够高效地实现各种查询。尝试使用单个持久数据模型支持所有查询通常具有挑战性,并且在某些情况下是不可能
3:在基于事件溯源技术的应用程序中实现查询
CQRS还克制了事件溯源的主要限制。事件存储库仅支持基于主键的查询。CQRS模式订阅由基于事件溯源的聚合发布的事件流,可以保持最新的聚合的一个或多个视图,由此解决此限制
4:更进一步地实现问题隔离
CQRS的另一个好处是它会隔离问题。领域模型及其相应的持久化数据模型不必同时处理命令和查询。CQRS为服务的命令端和查询端定义了单独的代码模块和数据库模式。
- CQRS的弊端
1:更加复杂的架构
CQRS的一个缺点是它使复杂性增加了。开发人员必须编写更新和查询视图的查询端服务。管理和运维额外的数据存储库提高了运维的复杂性。此外,应用程序可能使用不同类型的数据库,这进一步增加了开发人员和运维人员面临的复杂性
2:处理数据复制导致的延迟
CQRS的另一个缺点是处理命令端和查询端视图之间的“滞后”。
- 设计CQRS视图
CQRS视图模块包括由一个或多个查询操作组成的API。它通过订阅由一个或多个服务发布的事件来更新它的数据库视图,从而实现这些查询操作
在开发视图模块时,必须做以下重要的设计决策:
- 必须选择合适的数据库,并设计数据库结构
- 在设计数据访问模块时,必须解决各种问题,包括确保更新是幂等的,并且能够处理并发更新
- 在现有应用程序中实现新视图或更改现有应用程序的模式时,必须实现一种机制,以便有效地构建或重建视图
- 必须决定如何设计视图的客户端,以应对前面描述的复制延迟