微服务分布式一致性模式 – ThoughtWorks洞见

标签: | 发表时间:2019-09-06 15:00 | 作者:
出处:https://insights.thoughtworks.cn

微服务拆分后遇到的一个麻烦是分布后的一致性问题。单体架构的业务处理和数据都在一个进程里面,一致性保障很成熟,开发人员基本上不用关心。当把业务系统拆分到不同进程时,就遇到了技术性一致性问题。这带来了纠结,我们希望有一颗银弹,一把解决问题。但由于分布式一致性在(CAP)理论上没有完美的解决方案,我们所能选择的方案是在特定业务场景下的选择。

我们这里讨论的分布是指业务逻辑上做了拆分导致的分布,而不是数据量特别大导致的分布。

如果业务上不拆分,数据量特别大需要做分布,可以选择支持大数据的分布式数据库。可以选择Cassandra, MongoDB等NoSQL,或者TiDB这类支持SQL的分布式方案。

如果业务上进行了拆分,不论选什么数据库都不能解决分布式一致性问题。把数据库或者分布式数据库看成是一个系统,能处理一个外部请求在数据库内部的分布式问题,但不能处理多个外部请求的一致性问题。

分布式强一致的数据库不能解决业务逻辑拆分带来的分布式一致性问题,我们还得继续纠结如何解决业务分布式一致性的问题。

首先我把微服务分布式一致性问题分为数据共享一致性和业务交易一致性问题。

数据共享一致性

在单体架构的时候用同一个数据库,不存在数据共享问题。微服务强调要独立数据库,引起数据如何共享的问题。

数据共享分为拉和推两种模式,拉指消费者去供应商那边拉数据,推指供应商主动把数据推到消费者面前。

拉-视图共享

对于一般的企业信息系统,数据量不大,并发需求也不大,我建议所有的微服务用同一个数据库实例,但是拆分在不同的Schema。这样的好处是在业务逻辑上数据库是独立的,也可以独立演进。然后数据库又可以集中管理。 这个方案对于大型遗留系统拆分尤其适用,因为原本就是在一个库里面,为了业务更好的独立演进进行数据库Schema拆分,又能延续原有的数据库实例管理技术。由于不同的微服务实际运行在同一个数据库实例上,可以简单的建视图进行数据共享。 需要注意的是,不要拉整个表出去,根据需要选择几个字段。这种模式技术上简单,坏处有两个:一是由于视图同步的数据是实时的,应用可能基于实时同步数据的假设进行设计,会导致以后做分布式扩展的时候特别困难;二是视图很容易暴露出表结构,这需要特别加强对视图的设计和结构管理,让暴露出去的视图不要直接绑定在现有的表结构上。视图所需的字段是外部需要,而不是表上面有什么。这样视图就是接口,只不过是强耦合在特定的数据库实例上。

拉-API获取

微服务最推荐的方式是服务方提供数据API,消费者需要的时候去拉取。好处是消费者和供应方技术上完全解耦,坏处是提高了开发成本。如果消费者使用API方式获取所需数据,建议使用异步Stream方式进行编程。 如果一次业务请求需要拉取多个数据源,不建议用同步的方式调用,因为会延长处理时间。建议使用 reactiveX模式进行异步拉取和组装 。

推-事件消息

发生事件时发送消息是DDD CQRS模式,既解决了消费者要拥有数据用的爽快的问题(根据需要建立本地数据结构、获取性能和方式), 也解决了数据库技术异构的问题。带来的问题是需要一个消息平台,并且消费者或者供应方都要耦合在一个消息平台技术上。对于大型遗留系统改造不是很友好,一方面遗留系统的消息平台往往不符合高并发大数据量的性能要求,另一方面对于新的微服务也不想依赖老的消息平台,而想要用Kafka这样的互联网高并发轻量的消息平台。

数据共享一致性选择总结:

对于遗留系统改造和数据量不大(日交易量不超过百万)的应用,建议使用不同微服务创建不同Schema,但用同一个数据库实例,然后通过视图的方式进行数据共享。

如果有些业务数据量非常大又需要共享,使用API共享,利用异步Stream编程进行数据共享。

如果微服务平台技术设施成熟,可以使用推送事件消息模式, 即解决共享数据消费便利性问题,又解决数据结构解耦,并且使用轻量消息平台(Kafka)只是有轻度的技术耦合。

业务交易分布式一致性

业务交易分布式一致性指一次请求,但分布在不同的微服务系统处理,引发一致性协调的问题。

交易分布式一致性分为补偿模式,二次提交模式和Saga模式。

补偿模式

补偿模式主要是通过重试达到最后的成功,仅适用于交易请求在业务上必须没有失败的场景。

补偿模式用的最普遍的是消息投递,假设给A发消息,如果没有收到A确认消息已收到,就继续发送,直到A确认收到消息为止。

有很多业务可以变成必须成功的交易。比如下订单付款,如果先确认订单再去扣款,就有可能因为账户没钱扣款不成功,导致业务上的失败。如果业务改成先扣款再去确认订单,那可以认为订单必须要确认成功。通过业务顺序的调整来实现一个交易必须成功的情境。在技术实现上比较简单,利用一个任务队列跟踪任务的完成状态,来决定重试。补偿模式对API的要求是必须要幂等,因为有可能任务已经成功了,但消费者不知道,再次发出任务请求。

二次提交模式

由于补偿模式需要对业务进行调整,适用范围也比较小,我们还是希望有个通用的分布式一致性方案。

最有名的应该是二次提交模式,更具体点是TCC(Try,Confirm,Cancel)。先发起try请求让业务任务参与方做好处理准备,等所有的参与方都做好准备后,再发出confirm进行确认。因为所有的业务参与方都事前做好了准备,在confirm阶段可以确保一次性成功。如果有某个参与方失败,则发cancel进行回滚。这种模式和数据的事务管理基本一样,像Java的JTA实现Automikos就是从支持数据库事务,也支持REST API。二次提交虽然能解决事务一致性问题,但成本比较高。一个业务处理必须要拆分为准备和确认执行两个阶段,对业务设计要求和开发成本都比较高。

Sagas模式

Sagas模式的确保一致性程度和实现成本在补偿模式和二次提交模式之间,既简单又能广泛支持分布式事务场景。二次提交模式基于悲观锁,所以先要求任务参与方都做好准备,然后再做执行。Saga和补偿模式是基于乐观锁,先让任务参与方执行,如果执行没响应则要求再次执行。Saga给参与方发出任务后会记录一个event(Saga的中文翻译可以是事迹),所有event都会持久化。如果某个参与方执行失败,再发出cancel请求要求所有参与方回退。因为大部分交易请求是成功,这种基于乐观锁的协调机制能达成一致性目的,并降低了开发成本,业务设计上也比较容易理解。目前支持Saga的Java框架有华为开源的servicecomb saga,京东已经有些线上系统用了。还有做CQRS的框架axoniq也实现了saga。

参考文献

Saga论文

ServiceComb数据一致性解决方案Saga演进介绍

Saga模式


相关 [微服务 分布 一致性] 推荐:

微服务分布式一致性模式 – ThoughtWorks洞见

- -
微服务拆分后遇到的一个麻烦是分布后的一致性问题. 单体架构的业务处理和数据都在一个进程里面,一致性保障很成熟,开发人员基本上不用关心. 当把业务系统拆分到不同进程时,就遇到了技术性一致性问题. 这带来了纠结,我们希望有一颗银弹,一把解决问题. 但由于分布式一致性在(CAP)理论上没有完美的解决方案,我们所能选择的方案是在特定业务场景下的选择.

微服务下的数据一致性思考

- -
之前讲到了数据库层和缓存层的改造思路,而对于业务层的改造,采用了集中式服务转微服务的架构方案. 既然是微服务,就意味着面临大量的服务间的内部调用及服务依赖,这就意味着,如果一次请求的调用涉及到两个或多个微服务之间的调用,恰好有下游的微服务调用失败,我们就必须要考虑到回滚及服务间保证数据一致性的问题.

消息系统在微服务间通讯的数据一致性

- - 互联网 - ITeye博客
微服务是当下的热门话题,今天来聊下微服务中的一个敏感话题:如何保证微服务的数据一致性. 谈到分布式事务,就避免不了CAP理论. CAP理论是指对于一个分布式计算系统来说,不可能同时满足以下三点: . 一致性(Consistence) (等同于所有节点访问同一份最新的数据副本). 可用性(Availability)(对数据更新具备高可用性).

一文讲透微服务架构下如何保证事务的一致性

- - InfoQ推荐
随着业务的快速发展、业务复杂度越来越高,传统单体应用逐渐暴露出了一些问题,例如开发效率低、可维护性差、架构扩展性差、部署不灵活、健壮性差等等. 而微服务架构是将单个服务拆分成一系列小服务,且这些小服务都拥有独立的进程,彼此独立,很好地解决了传统单体应用的上述问题,但是在微服务架构下如何保证事务的一致性呢.

微服务数据一致性的演进:SAGA,CQRS,Event Sourcing的由来和局限-InfoQ

- -
讲微服务数据一致性的文章,网上比较多. 此前 EAWorld 与发过几篇,包括《 微服务架构下的数据一致性保证(一)》、《 微服务架构下的数据一致性保证(二)》、《 微服务架构下的数据一致性保证(三):补偿模式》,以及《 使用消息系统进行微服务间通讯时,如何保证数据一致性》. 本篇文章在我看来,是从一个纵向的维度把相关的一致性概念的演进过程,讲的比较清晰,简单的逻辑是这样的:.

微服务架构的分布式事务解决方案

- - 研发管理 - ITeye博客
分布式系统架构中,分布式事务问题是一个绕不过去的挑战. 而微服务架构的流行,让分布式事问题日益突出. 下面我们以电商购物支付流程中,在各大参与者系统中可能会遇到分布式事务问题的场景进行详细的分析. 如上图所示,假设三大参与平台(电商平台、支付平台、银行)的系统都做了分布式系统架构拆分,按上数中的流程步骤进行分析:.

微服务实现简单的分布式日志追踪

- - DockOne.io
最近想给项目添加一个简单的分布式请求跟踪功能,从前端发起请求到网关,再从网关调用 Spring Cloud 的微服务,这些过程中希望能从日志中看到一个分布式 ID 的链路,通过请求的 ID 可以追踪整一条链路,方便问题的排查. 现成的方案自然是使用 SkyWalking 、 Spring Cloud Sleuth 、Zipkin 之类的组件,但是想到主要的目的记录一个可以一直贯通各个服务的 ID,方便日志查询,也就不想引入太多复杂的组件,最终决定通过 MDC 在日志中输出追踪的 ID,然后在 Feign 和 RestTemplate 中将请求 ID 在微服务中传递.

分布式系统的事务及一致性模型

- Roger - NoSQLFan
下面PPT出自10gen的产品和工程高级副总裁 Roger Bodamer ,参加过Mongo Beijing的人应该记得会上的大个子. 下面PPT 主要就分布式系统的事务及一致性模型进行了分析和讨论. 对分布式存储在CAP原理下的选择和实现进行了描述. Google Megastore系统事务机制.

分布式系统中的事务一致性问题

- - CSDN博客架构设计推荐文章
在分布式系统中,我们经常遇到多数据副本保持一致的问题,在我们所能找到的资料中该问题讲的很笼统,模模糊糊的,把多个问题或分类糅合在一起,难以理解. 在思考和翻阅资料后,通俗地把一致性的问题可分解为2个问题:. 1、任何一次修改保证数据一致性. 在弱一致性的算法,不要求每次修改的内容在修改后多副本的内容是一致的,对问题1的解决比较宽松,更多解决问题2,该类算法追求每次修改的高度并发性,减少多副本之间修改的关联性,以获得更好的并发性能.

关于分布式系统的数据一致性问题

- - 互联网 - ITeye博客
现在先抛出问题,假设有一个主数据中心在北京M,然后有成都A,上海B两个地方数据中心,现在的问题是,假设成都上海各自的数据中心有记录变更,需要先同步到主数据中心,主数据中心更新完成之后,在把最新的数据分发到上海,成都的地方数据中心A,地方数据中心更新数据,保持和主数据中心一致性(数据库结构完全一致).