[第二部:容器和微服务架构] (7)分布式数据管理的挑战与解决方案

本文涉及的产品
数据管理 DMS,安全协同 3个实例 3个月
推荐场景:
学生管理系统数据库
云原生 API 网关,700元额度,多规格可选
简介: [第二部:容器和微服务架构] (7)分布式数据管理的挑战与解决方案

挑战1:如何定义每个微服务的边界


定义微服务边界可能是任何人遇到的第一个挑战。每个微服务都必须是应用程序的一部分,每个微服务都应该是自主的,具有它所传递的所有好处和挑战。但是你如何确定这些界限呢?

首先,您需要关注应用程序的逻辑域模型和相关数据。尝试在同一个应用程序中识别分离的数据孤岛和不同的上下文。每个上下文可以有不同的业务语言(不同的业务术语)。上下文应该独立定义和管理。在这些不同上下文中使用的术语和实体听起来可能类似,但您可能会发现,在特定上下文中,一个业务概念与另一个业务概念用于不同的上下文中,甚至可能有不同的名称。例如,用户可以在身份或成员关系上下文中被称为用户,在CRM上下文中被称为客户,在订购上下文中被称为买方,等等。

为每个上下文标识具有不同域的多个应用程序上下文之间的边界的方式,正是如何标识每个业务微服务及其相关域模型和数据的边界。您总是试图最小化这些微服务之间的耦合。本指南稍后将在《为每个微服务标识域模型边界》一节中详细介绍此标识和域模型设计。


挑战2:如何创建从多个微服务检索数据的查询


第二个挑战是如何实现从多个微服务检索数据的查询,同时避免从远程客户端应用程序与微服务进行聊天。例如,移动应用程序中的一个屏幕需要显示篮子、目录和用户标识微服务所拥有的用户信息。另一个例子是一个复杂的报表,其中包含位于多个微服务中的多个表。正确的解决方案取决于查询的复杂性。但无论如何,如果您想提高系统通信的效率,就需要一种聚合信息的方法。最流行的解决方案如下。


API网关。


对于来自拥有不同数据库的多个微服务的简单数据聚合,建议使用称为API网关的聚合微服务。但是,在实现这个模式时需要小心,因为它可能是系统中的一个瓶颈,并且可能违反微服务自治的原则。为了减少这种可能性,您可以拥有多个细粒度API网关,每个网关侧重于系统的垂直“部分”或业务区域。API网关模式将在后面的API网关部分中进行更详细的解释。


带有查询/读取表的CQRS(命令和查询责任隔离)


从多个微服务聚合数据的另一个解决方案是物化视图模式。在这种方法中,您可以预先(在实际查询发生之前准备非规范化的数据)生成一个只读表,其中包含多个微服务所拥有的数据。该表的格式适合客户端应用程序的需要。

考虑一下类似移动应用程序的屏幕。如果只有一个数据库,则可以使用SQL查询将该屏幕的数据拉到一起,该查询执行涉及多个表的复杂连接。但是,如果您有多个数据库,并且每个数据库都属于不同的微服务,则无法查询这些数据库并创建SQL联接。复杂的查询成为一个挑战。您可以使用CQRS方法来解决需求,您可以在一个仅用于查询的不同数据库中创建一个非规范化的表。该表可以专门为复杂查询所需的数据设计,应用程序屏幕所需的字段与查询表中的列之间具有一对一的关系。它也可用于报告目的。


这种方法不仅解决了最初的问题(如何跨微服务查询和连接),而且与复杂的连接相比,它还大大提高了性能,因为您已经在查询表中拥有应用程序所需的数据。当然,对查询/读取表使用命令和查询责任分离(CQRS)意味着需要额外的开发工作,您需要接受最终的一致性。尽管如此,协作场景(或竞争场景,取决于视角)中的性能和高可伸缩性要求是您应该对多个数据库应用cqr的地方。


中央数据库中的“冷数据”。


对于可能不需要实时数据的复杂报表和查询,一种常见的方法是将“热数据”(来自微服务的事务数据)作为“冷数据”导出到仅用于报表的大型数据库中。中央数据库系统可以是一个基于大数据的系统,比如Hadoop,一个基于Azure SQL数据仓库的数据仓库,甚至是一个只用于报表的SQL数据库(如果大小不是问题的话)。


请记住,这个集中式数据库只用于不需要实时数据的查询和报告。原始的更新和事务,作为您的真相来源,必须在您的微服务数据。同步数据的方式可以是使用事件驱动的通信(下一节将介绍)或使用其他数据库基础结构导入/导出工具。如果使用事件驱动的通信,那么集成过程将类似于前面为CQRS查询表所描述的传播数据的方式。


但是,如果您的应用程序设计涉及不断聚合来自多个微服务的信息以进行复杂的查询,则这可能是设计错误的征兆-微服务应尽可能与其他微服务隔离。(这不包括总是应该使用冷数据中心数据库的报表/分析)经常出现此问题可能是合并微服务的一个原因。您需要在每个微服务的演进和部署的自主性与强依赖性、内聚性和数据聚合之间取得平衡。


挑战3:如何跨多个微服务实现一致性


如前所述,每个微服务拥有的数据是该微服务的私有数据,只能使用其微服务API访问。因此,一个挑战是如何实现端到端业务流程,同时保持多个微服务之间的一致性。


为了分析这个问题,让我们看一个来自eShopOnContainers参考应用程序的示例。目录微服务维护所有产品的信息,包括产品价格。Basket microservice管理用户添加到购物篮中的产品项目的时间数据,其中包括添加到购物篮时的项目价格。当产品的价格在目录中更新时,该价格也应该在保存同一产品的活动篮中更新,另外,系统可能应该警告用户,说某个特定项目的价格自从添加到其篮中后已经发生了变化。


在这个应用程序的假设整体版本中,当products表中的价格发生变化时,catalog子系统可以简单地使用ACID事务来更新篮子表中的当前价格。

但是,在基于微服务的应用程序中,产品表和篮子表由各自的微服务拥有。任何微服务都不应该在自己的事务中包括另一个微服务拥有的表/存储,甚至在直接查询中也不应该包括,如图4-9所示。


微服务禁止直接访问另一个微服务中的表


Catalog microservice不应该直接更新Basket表,因为Basket表属于Basket microservice。为了更新Basket microservice,Catalog microservice应该使用可能基于异步通信(如集成事件(基于消息和事件的通信))的最终一致性。这就是eShopOnContainers引用应用程序如何跨微服务执行这种类型的一致性。


如CAP定理所述,您需要在可用性和ACID 强一致性之间进行选择。大多数基于微服务的场景要求可用性和高可伸缩性,而不是强一致性。任务关键型应用程序必须保持正常运行,开发人员可以通过使用处理弱一致性或最终一致性的技术来解决强一致性问题。这是大多数基于微服务的架构所采用的方法。

此外,ACID风格或两阶段提交事务不仅违反微服务原则;大多数NoSQL数据库(如Azure Cosmos DB、MongoDB等)不支持两阶段提交事务,这在分布式数据库场景中是典型的。然而,维护跨服务和数据库的数据一致性是必不可少的。这个挑战还涉及到当某些数据需要冗余时(例如,当您需要在目录微服务和篮子微服务中包含产品名称或描述时),如何在多个微服务中传播更改的问题。


解决这个问题的一个很好的方法是使用事件驱动通信和发布和订阅系统所连接的微服务之间的最终一致性。本指南后面的异步事件驱动通信一节将介绍这些主题。


挑战4:如何设计跨越微服务边界的通信


跨越微服务边界进行通信是一个真正的挑战。在这种情况下,通信并不是指应该使用什么协议(HTTP和REST、AMQP、消息传递等等)。相反,它解决了您应该使用什么样的通信方式,特别是您的微服务应该如何耦合。根据耦合的级别,当发生故障时,该故障对系统的影响将有很大的不同。


在像基于微服务的应用程序这样的分布式系统中,有这么多工件在移动,并且有跨多个服务器或主机的分布式服务,组件最终将失败。部分故障甚至更大的中断都会发生,因此您需要考虑到这种分布式系统中的常见风险,设计您的微服务和它们之间的通信。


一种流行的方法是实现基于HTTP(REST)的微服务,因为它们很简单。基于HTTP的方法是完全可以接受的;这里的问题与您如何使用它有关。如果使用HTTP请求和响应只是为了与来自客户端应用程序或API网关的微服务交互,那就没问题了。但是,如果您跨微服务创建长链的同步HTTP调用,并跨其边界进行通信,就好像微服务是单片应用程序中的对象一样,那么您的应用程序最终将遇到问题。


例如,假设您的客户机应用程序对单个微服务进行HTTP API调用,就像对微服务进行排序一样。如果顺序微服务在同一请求/响应周期内使用HTTP调用其他微服务,则创建一个HTTP调用链。一开始听起来可能很合理。然而,在沿着这条路走下去时,需要考虑的要点有:


  • 阻塞和低性能。由于HTTP的同步特性,原始请求在所有内部HTTP调用完成之前不会得到响应。想象一下,如果这些调用的数量显著增加,同时对微服务的一个中间HTTP调用被阻塞。结果是性能受到影响,并且随着额外的HTTP请求的增加,总体可伸缩性将受到指数级的影响。

  • 将微服务与HTTP耦合。业务微服务不应与其他业务微服务耦合。理想情况下,他们不应该“知道”其他微服务的存在。如果应用程序依赖于耦合微服务(如示例所示),则几乎不可能实现每个微服务的自治。

  • 任何一个微服务出现故障。如果实现了一个由HTTP调用链接的微服务链,那么当任何一个微服务失败(最终它们将失败)时,整个微服务链都将失败。应设计一个基于微服务的系统,以便在部分故障期间尽可能继续工作。即使实现了使用指数退避或断路器机制重试的客户端逻辑,HTTP调用链越复杂,实现基于HTTP的故障策略就越复杂。


事实上,如果您的内部微服务是通过创建所述的HTTP请求链进行通信的,那么可以认为您有一个单片应用程序,但它是基于进程间HTTP而不是进程内通信机制的应用程序。


因此,为了强制微服务自治并具有更好的弹性,您应该尽量减少跨微服务的请求/响应通信链的使用。建议您只使用异步交互进行微服务间通信,可以使用异步消息和基于事件的通信,也可以使用(异步)HTTP轮询,独立于原始HTTP请求/响应周期。


异步通信的使用将在本指南后面的“异步微服务集成实施微服务的自治和基于异步消息的通信”一节中详细说明。


额外资源

相关实践学习
MySQL基础-学生管理系统数据库设计
本场景介绍如何使用DMS工具连接RDS,并使用DMS图形化工具创建数据库表。
相关文章
|
28天前
|
Dubbo Java 应用服务中间件
Spring Cloud Dubbo:微服务通信的高效解决方案
【10月更文挑战第15天】随着信息技术的发展,微服务架构成为企业应用开发的主流。Spring Cloud Dubbo结合了Dubbo的高性能RPC和Spring Cloud的生态系统,提供高效、稳定的微服务通信解决方案。它支持多种通信协议,具备服务注册与发现、负载均衡及容错机制,简化了服务调用的复杂性,使开发者能更专注于业务逻辑的实现。
51 2
|
1月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
100 3
|
2月前
|
存储 SQL 微服务
常用的分布式事务解决方案(三)
常用的分布式事务解决方案(三)
|
2月前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
2月前
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1
|
3天前
|
传感器 算法 物联网
智能停车解决方案之停车场室内导航系统(二):核心技术与系统架构构建
随着城市化进程的加速,停车难问题日益凸显。本文深入剖析智能停车系统的关键技术,包括停车场电子地图编辑绘制、物联网与传感器技术、大数据与云计算的应用、定位技术及车辆导航路径规划,为读者提供全面的技术解决方案。系统架构分为应用层、业务层、数据层和运行环境,涵盖停车场室内导航、车位占用检测、动态更新、精准导航和路径规划等方面。
27 4
|
16天前
|
运维 Serverless 数据处理
Serverless架构通过提供更快的研发交付速度、降低成本、简化运维、优化资源利用、提供自动扩展能力、支持实时数据处理和快速原型开发等优势,为图像处理等计算密集型应用提供了一个高效、灵活且成本效益高的解决方案。
Serverless架构通过提供更快的研发交付速度、降低成本、简化运维、优化资源利用、提供自动扩展能力、支持实时数据处理和快速原型开发等优势,为图像处理等计算密集型应用提供了一个高效、灵活且成本效益高的解决方案。
51 1
|
1月前
|
运维 Serverless 数据处理
Serverless架构通过提供更快的研发交付速度、降低成本、简化运维、优化资源利用、提供自动扩展能力、支持实时数据处理和快速原型开发等优势,为图像处理等计算密集型应用提供了一个高效、灵活且成本效益高的解决方案。
Serverless架构通过提供更快的研发交付速度、降低成本、简化运维、优化资源利用、提供自动扩展能力、支持实时数据处理和快速原型开发等优势,为图像处理等计算密集型应用提供了一个高效、灵活且成本效益高的解决方案。
57 3
|
30天前
|
消息中间件 存储 负载均衡
微服务与分布式系统设计看这篇就够了!
【10月更文挑战第12天】 在现代软件架构中,微服务和分布式系统设计已经成为构建可扩展、灵活和可靠应用程序的主流方法。本文将深入探讨微服务架构的核心概念、设计原则和挑战,并提供一些关于如何在分布式系统中实现微服务的实用指导。
49 2
|
1月前
|
人工智能 文字识别 Java
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?
尼恩,一位拥有20年架构经验的老架构师,通过其深厚的架构功力,成功指导了一位9年经验的网易工程师转型为大模型架构师,薪资逆涨50%,年薪近80W。尼恩的指导不仅帮助这位工程师在一年内成为大模型架构师,还让他管理起了10人团队,产品成功应用于多家大中型企业。尼恩因此决定编写《LLM大模型学习圣经》系列,帮助更多人掌握大模型架构,实现职业跃迁。该系列包括《从0到1吃透Transformer技术底座》、《从0到1精通RAG架构》等,旨在系统化、体系化地讲解大模型技术,助力读者实现“offer直提”。此外,尼恩还分享了多个技术圣经,如《NIO圣经》、《Docker圣经》等,帮助读者深入理解核心技术。
SpringCloud+Python 混合微服务,如何打造AI分布式业务应用的技术底层?