使用API组合模式进行查询
让拥有数据的服务的客户端负责调用服务,并组合服务返回的查询结果。
两类角色:
- API组合器
- 数据提供方服务
由谁担任API组合器角色:
- 客户端担任,但这对于防火墙之外客户以及通过较慢网络访问的服务,此选择不实用。
- API Gateway中实现,API查询提供方服务,检索数据,组合结果并向客户端返回响应。
- API组合器,将多个客户端和服务使用的查询操作实现为独立的服务,可实现API Gateway无法完成的复杂的聚合逻辑。应使用响应式编程模式,尽可能并行调用服务,最大限度地缩短查询操作的响应时间
API组合模式的好处与弊端
弊端:
- 增加了额外的开销
- 带来了可用性降低的风险
- 缺乏事务数据一致性
好处:简单直观
使用CQRS模式
使用事件来维护从多个服务复制数据的只读视图,借此实现对来自多个服务的数据的查询。
为什么要使用CQRS
- 使用API组合模式检索分散在多个服务中的数据会导致昂贵、低效的内存中连接(如某些服务并不存储用于过滤的属性)
- 拥有数据的服务将数据存储在不能有效支持所需查询的表单或数据库中(如无法执行有效的地理空间查询)
- 鉴于隔离(避免过多的职责导致过载服务)考虑,拥有数据的服务不一定是会实现查询操作的服务。
什么是CQRS
CQRS隔离命令和查询
命令查询职责隔离。将持久化数据模型和使用数据的模块分为两部分:命令端和查询端。命令端模块和数据模型实现CUD操作,查询端模块和数据模型实现查询。查询端通过订阅命令端发布的事件,使其数据模型与命令端数据模型保持同步。
CQRS和查询专用服务
CQRS不仅可以服务中应用,还可以定义查询专用服务。它的API只包含查询操作,通过订阅由一个或多个其他服务发布的事件来确保它的数据库是不断更新的,并由此实现查询操作。
CQRS的好处
- 在微服务架构中高效地实现查询
- 高效地实现多个不同的查询类型
- 在基于事件溯源技术的应用中实现了查询
- 更进一步地实现问题隔离
CQRS的弊端
- 更加复杂的架构
- 处理数据复制导致的延迟 一种解决方案是采用命令端和查询端API为客户端提供版本信息,使其能够判断查询端是否过时。
- 应尽可能使用API组合
设计CQRS视图
CQRS视图模块包括由一个或多个查询操作组成的API。它通过订阅由一个或多个服务发布的事件来更新其数据库视图,从而实现这些查询操作。
选择视图数据库
SQL还是NoSQL数据库
NoSQL数据库通常具有有限的事务模型和较少的查询功能,但在一些情况下,具有更灵活的数据模型以及更好的性能和可扩展性
支持更新操作
事件处理程序通常使用其主键更新或删除视图数据库中的记录,但有时,也需要使用类似外键的做法来更新或删除记录,这对某些NoSQL数据库而言不是很容易,应用需要维护某种特定于数据库的映射,从外键到主键,以确定更新的记录。
设计数据访问模块
事件处理程序和查询API模块不直接访问数据存储区,相反,它们使用数据访问模块,该模块由DAO及其辅助类组成。
并发处理
若视图订阅由多个聚合类型发布的事件,则多个事件处理程序可能同时更新同一记录。
不能允许一次更新覆盖另一次更新。若DAO通过读取记录进行更新,然后再写入已更新记录的做法,必须使用悲观锁或乐观锁。
幂等事件处理程序
事件处理程序可以是幂等的,但重复事件可能会使对象状态暂时过时,因此可以检测并丢弃重复事件。
由于消息传递基础设施延迟,视图是最终一致的。
添加或更新CQRS视图
使用归档事件构建CQRS视图
消息代理无法无限期存储消息。应用程序还必须读取已存档的旧事件(也许已被保存到AWS S3),可以使用可扩展的大数据技术实现此目的。
增量式构建CQRS视图
所处理事件所需要的时间、资源随着时间推移不断增长。可以采用两步增量法,使用快照。