当前位置: 首页 > 知识库问答 >
问题:

跨微服务的数据一致性

欧阳绪
2023-03-14

虽然每个微服务通常都有自己的数据,但某些实体需要在多个服务之间保持一致。

对于高度分布式环境(如微服务体系结构)中的这种数据一致性要求,设计的选择是什么?当然,我不想要共享数据库体系结构,即单个数据库管理所有服务的状态。这违反了孤立和不共享的原则。

我明白,微服务可以在创建、更新或删除实体时发布事件。对该事件感兴趣的所有其他微服务可以相应地更新各自数据库中的链接实体。

这是可行的,但是它会导致跨服务进行大量仔细和协调的编程工作。

Akka或任何其他框架可以解决这个用例吗?怎样

编辑1:为了清晰起见,添加下面的图表。
基本上,我试图理解,今天是否有可用的框架可以解决这个数据展示一致性问题。

共有3个答案

莫承运
2023-03-14

这里也有同样的问题。我们在不同的微服务中有数据,在某些情况下,一个服务需要知道另一个微服务中是否有特定的实体。我们不希望服务相互调用以完成请求,因为这会增加响应时间和多个停机时间。它还增加了耦合深度的噩梦。客户也不应该决定业务逻辑和数据验证/一致性。我们也不希望像“Saga控制器”这样的中央服务提供服务之间的一致性。

因此,我们使用Kafka消息总线将“上游”服务中的状态变化通知观察服务。即使在出错的情况下,我们也尽量不遗漏或忽略任何消息,我们使用Martin Fowler的“宽容读者”模式尽可能松散地进行耦合。但有时服务会被更改,更改后,他们可能需要来自其他服务的信息,这些信息以前可能在总线上发出,但现在已经不存在了(即使是Kafka也无法永远存储)。

我们现在决定将每个服务拆分为一个纯的、解耦的web服务(RESTful)和一个单独的连接器服务,前者执行实际工作,后者侦听总线,还可以调用其他服务。此连接器在后台运行。它仅由总线消息触发。然后,它将尝试通过REST调用向主服务添加数据。如果服务响应一致性错误,连接器将尝试通过从上游服务获取所需数据并根据需要注入数据来修复此错误。(我们负担不起批量作业来“同步”数据块,所以我们只获取所需的数据)。如果有更好的想法,我们总是开放的,但“拉”或“只是改变数据模型”不是我们认为可行的…

翟新
2023-03-14

理论局限性

需要记住的一个重要警告是CAP定理:

如果存在分区,则剩下两个选项:一致性或可用性。在选择一致性而非可用性时,如果由于网络分区而无法保证特定信息是最新的,系统将返回错误或超时。

因此,通过“要求”某些实体在多个服务中保持一致,您就增加了处理超时问题的可能性。

Akka分布式数据

Akka有一个分布式数据模块,用于在集群内共享信息:

所有数据条目通过直接复制和基于闲话的传播传播到集群中的所有节点或具有特定角色的节点。您可以对读写的一致性级别进行细粒度控制。

聂琨
2023-03-14

微服务体系结构风格试图允许组织拥有独立于开发和运行时的小团队自己的服务。看到这读。最难的部分是以一种有用的方式定义服务边界。当您发现您拆分应用程序的方式导致需求经常影响多个服务时,这将告诉您重新考虑服务边界。当您强烈需要在服务之间共享实体时,情况也是如此。

因此,一般的建议是尽量避免这种情况。但是,在某些情况下,您无法避免这种情况。因为一个好的架构通常是关于做出正确的权衡,这里有一些想法。

>

  • 考虑使用服务接口(API)而不是直接的DB依赖来表达依赖关系。这将允许每个服务团队根据需要更改其内部数据模式,并且只在涉及依赖时担心接口设计。这很有帮助,因为更容易添加额外的API并缓慢地弃用旧的API,而不是更改数据库设计以及所有依赖的微服务(可能同时)。换句话说,只要仍然支持旧的API,您仍然可以独立部署新的Microservice版本。这是亚马逊首席技术官推荐的方法,他开创了许多微服务方法。以下是2006年对他的采访推荐阅读。

    当您确实无法避免使用相同的DBs,并且您正在以多个团队/服务需要相同实体的方式分割您的服务边界时,您将在微服务团队和负责数据方案的团队之间引入两种依赖关系:a)数据格式,b)实际数据。这不是不可能解决的,只是需要组织中的一些开销。如果您引入了太多这样的依赖关系,您的组织很可能会瘫痪,并且在开发过程中会放慢速度。

    a) 依赖于数据方案。如果不需要更改微服务,则无法修改实体数据格式。要将其解耦,您必须严格地对entities数据方案进行版本设置,并且在数据库中支持微服务当前使用的所有数据版本。这将允许微服务团队自行决定何时更新其服务以支持新版本的数据方案。这并不适用于所有用例,但适用于许多用例。

    b) 依赖于实际收集的数据。已收集的数据以及已知版本的Microservice数据可以使用,但当某些服务生成较新版本的数据,而另一个服务依赖于该数据,但尚未升级到能够读取最新版本时,就会出现问题。这个问题很难解决,在许多情况下,这表明您没有正确选择服务边界。通常,您别无选择,只能在升级数据库中的数据的同时推出所有依赖于数据的服务。一种更古怪的方法是并发地编写不同版本的数据(这主要在数据不可变时起作用)。

    为了解决a)和b)这两个问题,在其他一些情况下,可以通过隐藏数据重复最终一致性来减少依赖性。这意味着每个服务都存储自己的数据版本,并且只在该服务的需求发生变化时才对其进行修改。这些服务可以通过监听公共数据流来实现。在这种情况下,您将使用基于事件的体系结构,在这种体系结构中,您可以定义一组公共事件,这些事件可以由来自不同服务的侦听器排队并使用,这些服务将处理事件并存储其中与事件相关的任何数据(可能会创建数据复制)。现在,一些其他事件可能表明必须更新内部存储的数据,每个服务都有责任使用自己的数据副本进行更新。维护这种公共事件队列的技术是Kafka。

  •  类似资料:
    • 我正在计划一个使用事件源的微服务模型。为了实现高可伸缩性和高吞吐量处理能力,我将使用Kafka作为微服务的消息代理。 在这一点上,我有问题的实现模型,以能够拥有Kafka主题和分区的好处。我的模型需要满足一些要求: 微服务必须从message broker获取数据(post/patch/put/delete) 数据一致性是强制性的,如果实体A需要实体B的先前存在,则必须只存在实体A的指向实体B的有

    • 第1步:我想有一个

    • 我不清楚如何取回购买服务不保存的数据--例如:用户的全名。当试图通过购买用户名进行更复杂的搜索购买时,问题会变得更严重。 我认为,显然可以通过在两个服务之间同步用户来解决这个问题,方法是在用户创建时广播某种类型的事件(并在购买服务端只保存相关的用户属性)。在我看来,这远非理想。当你有数百万用户时,你如何处理这个问题?您会在每个使用用户数据的服务中创建数百万条记录吗? 另一个明显的选择是在用户服务端

    • 假设我们有一个用户、Wallet REST微服务和一个将事情粘合在一起的API网关。当Bob在我们的网站注册时,我们的API网关需要通过用户微服务创建一个用户,通过钱包微服务创建一个钱包。 下面是一些可能出错的场景: > 用户Bob创建失败:没关系,我们只需向Bob返回一个错误消息。我们使用的是SQL事务,所以没有人在系统中看到Bob。一切都很好:) 创建了用户Bob,但在创建钱包之前,我们的AP

    • 例如,我们有带有事件源的微服务。为实现数据一致性,我们采用以下方法: 微服务生成事件 事件存储在事件存储中 事件将发布到订阅的微服务 这种方法适用于已经在使用的微服务。但是,如果我需要部署另一个需要与事件存储同步数据的微服务,该怎么办?显然,这个新的微服务错过了所有发布的事件。 这个新的微服务应该自己从事件存储中提取事件吗?

    • 主要内容:1、再回顾:什么是服务注册中心?,2、Consul服务注册中心的整体架构,3、Consul如何通过Raft协议实现强一致性?,4、Consul如何通过Agent实现分布式健康检查?1、再回顾:什么是服务注册中心? 先回顾一下什么叫做服务注册中心? 顾名思义,假设你有一个分布式系统,里面包含了多个服务,部署在不同的机器上,然后这些不同机器上的服务之间要互相调用。 举个现实点的例子吧,比如电商系统里的订单服务需要调用库存服务,如下图所示。 现在的问题在于,订单服务在192.168.31.1