怎样实现跨微服务的数据查询?

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 怎样实现跨微服务的数据查询?

微服务是很好,但如果每个服务都有自己的数据库,那怎么连接不同服务的数据,从而提供统一的查询呢?这篇文章按照微服务改造的不同阶段,给出了解决方案。原文:MicroServices: How do we join the data among different microservices?[1]

image.png

如何连接不同数据库中的数据?


image.png

Monolith 和 Microservices 数据库结构比较


让我们从一个简单的问题开始:假设我们有一个需要进行微服务改造的单体系统,这个系统用于支持用户通过邮件购买产品。那么问题来了,在微服务化后,我怎么能够知道通过邮件购买产品 A、B 或 C 的所有用户?


就像 IT 世界的任何事情一样,没有绝对正确或错误的解决方案,根据具体用例,一种方案可能比另一种更合适。我们始终需要平衡不同解决方案的利弊,并将其应用到特定环境和开发文化中。有时候,快速的解决方案可以帮助我们在市场中生存下来,而持久和复杂的解决方案可以帮助我们在未来迅速扩大规模!


本文给出的解决方案将涵盖我们在微服务之旅中所经历的任何情况,并解释其利弊。


使用单一数据库集群(利用 Schema 或表)


image.png

使用单一数据库集群的微服务数据架构


如果不同的微服务都访问同一个数据库集群,这种解决方案会很有用,其主要思想是为不同的服务定义不同的 Schema/表。


image.png

每个服务负责往自己的表里写入其数据,从其他服务的 Schema/表中读取数据


经验法则


写数据:只有拥有数据的微服务的写入请求才被允许。

读数据:任何需要数据的服务都可以读取数据。


如果决定在同一个数据库中使用该模式,需要更新所有查询以启用交叉连接。以上面的例子为例,假设我们想知道所有购买产品 A、B 或 C 的用户。


# Using a different schema (Same Database Cluster)
SELECT ut.email FROM purchase_schema.purchase_table pt INNER JOIN user_schema.user_table ut ON pt.userId = ut.id WHERE pt.product.productTag IN ('A','B','C');
# Using the same table (Same Database Cluster)
SELECT ut.email FROM purchase_table pt INNER JOIN user_table ut ON pt.userId = ut.id WHERE pt.product.productTag IN ('A','B','C');


好处:


  1. 如果要连接的 Schema 和表使用相同的字符集以及相同类型的外键,则可以利用索引。
  2. 从开发的角度来看,更容易实现,一切都基于 SQL 查询。
  3. 这是开始进行微服务化改造的第一步,能够了解系统是否设计良好,并准备好完全解耦。


坏处:


  1. 单一数据库集群意味着单点故障乘以系统中微服务数量,只需要有一个微服务执行了一个消耗资源的查询就可以影响到所有其他的微服务。
  2. 需要为每个服务创建一个用户,并确保将用户配置为在特定表或特定 Schema 上写/只读。


使用多个数据库:复制数据


image.png

两个微服务及其数据库,没有复制数据,因此无法连接数据以检索用户的电子邮件


当我们把数据从单一数据库集群中移出时,就失去了在数据之间进行连接的能力。因此,如果我们仍然需要进行大量数据的连接并创建一个冗长的报告,怎么办才好呢?一种简单的方法是进行数据复制。即使我们能够想到一个解决方案解决大量数据连接的问题,但并不一定有时间构建和实现这样的解决方案。


黄金法则


写数据:只允许与数据库相关的微服务写入数据(例如,服务 1 只能在数据库服务 1 中写入)。


读数据:允许从复制数据的任何数据库中读取数据。


好处:


  1. 在微服务所在的数据库中数据是可用的,因此可以执行 join 操作。
  2. 只能复制需要的数据。
  3. 非常快,大部分时间很容易配置。


坏处:


  1. 需要设置规则,不允许微服务修改复制的数据。
  2. 数据是近实时可用的。
  3. 需要一个适当的流程来复制数据。
  4. 如果复制失败,数据将不同步。


使用 AWS DMS 复制数据


image.png


如果需要将数据从一个数据库集群复制到另一个数据库集群,可以使用 AWS DMS(数据迁移服务)。该服务允许从两个不同的数据库复制数据,并且允许应用基本的 ETL 转换。


如果只想传输部分数据,或者需要更改列名等信息时,ETL 转换非常方便。使用 AWS DMS 的唯一问题是索引,编写管理索引的简单方法的时机是:

  • 启动和停止复制(需要在复制数据库上创建表/模式)
  • 手动应用索引
  • 再次启动正在进行的复制


拥有一个完整的副本意味着仍然能够像之前那样执行 join 操作,实现接近实时的读取。


# The tables will be in the same schema therefore:
SELECT ut.emails FROM purchase_table pt INNER JOIN user_table ut ON pt.userId = ut.id WHERE pt.product.productTag IN ('A','B','C');


事件(AWS kineesis 或 AWS Lambda)

image.png


如果你正在使用事件驱动架构(EDA,Event-Driven Architecture),AWS Kinesis 或者 SQS 和 Lambda 的组合绝对值得一看!然而,即使你没有使用 EDA,而只用 AWS,也会发现这个场景非常有趣。


如果你已经部署了 AWS RDS Serverless,并且希望将数据复制到另一个数据存储中,不幸的是,没法用 AWS DMS,原因很简单,AWS RDS Serverless 没有 binlog(这会在下个版本中修复)。


当我们需要多个参与者侦听数据并对更改采取行动时,这种方法是最好的。本例中,User 服务将发出一个事件,表示他的域中的一些数据发生了更改。作为侦听器的 Product 服务将接收更改并修改数据。


AWS Kinesis 可以被直接调用微服务的简单 REST API 所取代。


节约生命法则


永远尝试在当前场景中 1:1 的复制数据,这将在灾难发生的时候拯救你!即使引入了一个错误,并且侦听器没有正确插入数据,也可以在当天修复这个错误。我们可以将数据库 A 转储到数据库 B 中,而不是从头开始重新处理所有事件。


# Same case as before, tables in the same schema:
SELECT ut.emails FROM purchase_table pt INNER JOIN user_table ut ON pt.userId = ut.id WHERE pt.product.productTag IN ('A','B','C');


使用单个或多个数据库:API 调用


在构建微服务时,应该始终牢记 API First,这将使服务之间无缝沟通。

image.png

在这个例子中,如果我们想获取某个用户购买的产品记录,非常简单,只需要向 Product 服务询问我们想要查询的用户的 ID,然后使用 Product 服务检索我们要查找的数据。


在本例中,我们希望检索购买产品 A、B、C 的所有用户的电子邮件,因此,可以遵循以下操作流程:


1) Product Service 
    -> SQL to retrieve all the unique User ID that purchased product A,B,C in the past
    -> SELECT * FROM product WHERE product_ID in ('A','B','C');
2) Product Service do a REST API call to 
    -> Service 1 asking Email for each of the User Id retrieved on step 1
3) Aggregate the outputs and return the result


好处:


  1. 数据是完全独立和隔离的
  2. 每个微服务可以彼此通信,请求关于其他微服务领域的信息


坏处:


  1. 网络延时
  2. 查询信息越多,操作就会越慢。想象一下为 5000 万用户请求信息。


API 批量调用


如果数据库中有很多用户,可以使用批量调用加快信息检索。


好处和坏处和之前的解决方案差不多,根据使用的架构,可以使用一些多路复用(多线程/协程)技术加速。


聚合服务


当我们希望以接近实时的方式处理数据时,聚合服务是很好的选择。有很多种具体实现的技术,可以混合使用直接 API 调用、事件或数据转储,都没有关系。


image.png


在本例中,将向你展示如何使用事件构建解决方案并传递不同的服务结果。

image.png

发出事件的服务和接收事件的其他服务


如果 Product 服务和 User 服务发出事件,聚合服务可以接收事件并根据需要处理数据。下面以 Service 3 为例,给出一个更详细的示例:


image.png

监听并处理事件,将事件存储在一个新的数据存储中


监听事件,一旦收到事件,就进行需要的转换,然后将它保存到 ElasticSerach 中以方便检索。


结论


通信是微服务的基础,在实现本文(或资源部分中提到的书)中的任何解决方案之前,要权衡你的资源并了解你的用例。


资源

O’Reilly: Monolith To Microservices[2]


image.png

O’Reilly: Building Microservices[3](中文版:《微服务设计》[4]


image.png


References:

[1] https://medium.com/creditorwatch/join-data-among-microservices-1cda360c6c1c

[2] https://www.oreilly.com/library/view/monolith-to-microservices/9781492047834/

[3] https://www.oreilly.com/library/view/building-microservices-2nd/9781492034018/

[4] https://book.douban.com/subject/26772677/

目录
相关文章
|
26天前
|
数据库 微服务 NoSQL
探索微服务架构下的数据库选型与优化策略
在现代软件开发中,微服务架构已成为一种常见的设计范式。而数据库在微服务架构中的选型与优化策略对整个系统的性能和稳定性至关重要。本文将探讨在微服务环境下,如何选择适合的数据库类型以及优化数据库性能的策略。
|
2天前
|
NoSQL Java 数据库
优化基于阿里云的微服务架构下的数据库访问性能
在应对大型电商项目中数据库访问性能瓶颈问题时,团队通过阿里云工具分析发现高QPS、慢查询和不合理数据交互是关键。优化措施包括:1) 索引优化,针对慢查询添加或调整索引;2) 开启读写分离,使用RDS读写分离功能和DRDS进行水平拆分;3) 引入Redis缓存热点数据,减少直接数据库访问;4) 服务化数据访问,降低跨服务数据库调用;5) 使用Sentinel进行限流和熔断,保护数据库资源。这些改进显著提升了系统响应速度和用户体验。
|
9月前
|
存储 数据库 开发者
单元化架构的设计原则:让开发者、组件和数据都能透明化,同时保证业务可分片和业务自包含。
单元化架构的设计原则:让开发者、组件和数据都能透明化,同时保证业务可分片和业务自包含。
|
缓存 前端开发 安全
55-微服务技术栈(高级):微服务网关Soul(数据同步原理)
Soul 网关在启动时,会从从配置服务同步配置数据,并且支持推拉模式获取配置变更信息,并且更新本地缓存。而管理员在管理后台,变更用户、规则、插件、流量配置,通过推拉模式将变更信息同步给 Soul 网关,具体是 push 模式,还是 pull 模式取决于配置。关于配置同步模块,其实是一个简版的配置中心。
411 0
|
前端开发 Java 关系型数据库
分布式微服务系统的跨库查询/操作的解决思路(关系型数据库)
分布式微服务系统的跨库查询/操作的解决思路(关系型数据库)
3812 0
|
存储 运维 前端开发
表结构设计—高并发场景微服务实战(五)
你好,我是程序员Alan。 这篇文章我会详细讲一下设计表结构时我会重点关注的地方,助你少走弯路。
189 0
表结构设计—高并发场景微服务实战(五)
|
数据采集 运维 监控
分布式统一监控系统架构图与设计思路| 学习笔记
快速学习分布式统一监控系统架构图与设计思路。
370 0
分布式统一监控系统架构图与设计思路| 学习笔记
|
数据采集 运维 监控
分布式统一监控系统架构图与设计思路
一、问题解答 二、分布式统一系统 三、统一监控系统架构图 四、设计思路
分布式统一监控系统架构图与设计思路
|
消息中间件 Oracle 关系型数据库
「跨数据库、微服务」 FreeSql 分布式事务 TCC/Saga 编排重要性
FreeSql 支持 MySql/SqlServer/PostgreSQL/Oracle/Sqlite/Firebird/达梦/Gbase/神通/人大金仓/翰高/Clickhouse/MsAccess Ado.net 数据库,以及 Odbc 的专门实现包。 FreeSql.Cloud 为 FreeSql 提供跨数据库访问,分布式事务TCC、SAGA解决方案,支持 .NET Core 2.1+, .NET Framework 4.0+.
|
存储 运维 负载均衡
聊聊集群、分布式和微服务之间的联系和异同点
对于集群、分布式和微服务,大家在工作中可能经常会听到,但是如果问你它们之间存在什么样的区别和联系,可能你一下子又感觉说不清楚,今天就这个话题,趁着周末时间,跟大家来一起聊聊。
聊聊集群、分布式和微服务之间的联系和异同点

热门文章

最新文章