Micro-service architecture to achieve the ultimate consistency of the three modes

  According to CAP theory, you must make a choice between availability (Availability) and consistency (Consistency). If you choose to provide consistency, you need to pay for blocking other concurrent access before to meet the expense of consistency. This may continue for some time uncertain, especially system already exhibit high latency due to network failure or lost connection.
  According to the current successful experience, choose the general availability of micro-services architecture is more conducive to the construction, but maintaining data consistency is very fundamental needs between the service and the database, in micro-services architecture should be selected to meet the eventual consistency. Of course, necessary to ensure consistency selected to meet the end user within the acceptable range delay between the service from the start to finish .
  The essence is to ensure a consistent business logic contained in the service are either succeed or fail. So choose a guarantee of success (retried) or choose to guarantee failure (rollback) it? It often depends on the business model.
Here Insert Picture Description
  There are 3 ultimate consistency in business models: reliable event model, business compensation mode, TCC mode.

Reliable Event Mode 1

  Reliable sources mode belong to event-driven architecture. When something important happens, such as updating a business entity, micro service will be the news agency released a event , message broker will micro services to subscribe to the events of the push event , when the subscription micro serve these events receives this message, it you can complete their business, but also may lead to more events published.
  For example, order a service order is created to be paid, then the time will be issued a "create order", as shown:
Here Insert Picture Description
  payment service consumer "create order" time, pay issued a "pay for success" after the completion of the event, as shown in show:
Here Insert Picture Description
  order service consumption, "successful payment" event, order status update to be out of the library, as shown:
Here Insert Picture Description
  At this point, will complete the entire business process.

  但是这并不是一个完美的流程,在这个过程中可能出现多种数据不一致的场景。
1、如果微服务在更新了业务实体后,却发布事件失败;
2、虽然微服务发布事件成功,但是消息代理未能正确推送事件到订阅的微服务;3、接受事件的微服务重复消费了事件。
  可靠事件模型的特点在于保证可靠事件投递避免重复消费。可靠事件投递要求:
1、每个服务都要进行原子性业务操作事件发布
2、消息代理确保事件至少投递一次
  避免重复消费要求服务实现幂等性,如支付服务不能因为重复收到事件而多次支付。现在流行的消息队列都实现了事件的持久化和at least once(至少一次)的投递模式,第二个特性(消息代理确保事件至少投递一次)已经满足,此处不做展开。
  下面主要从可靠事件投递和实现幂等性两方面来讨论。先来看可靠事件投递。我们一如下代码片段为例

public void trans(){
	try{
		// 1、操作数据库
		bool result = dao.update(model);//操作数据库失败会抛出异常
		// 2、如果第一步成功,则操作消息队列(投递消息)
		if(resul){
			mq.append(model);//如果消息投递失败,会抛出异常
		}
	}catch(Exception e){
		// 3、如果发生异常,回滚事务
		rollback();
	}
}

  根据上述代码及注释,初看可能会发现操作数据库时会有3中情况
1、操作数据库成功,消息投递成功
2、操作数据库失败,不会投递消息
3、操作数据库成功,消息投递失败,数据库操作被回滚。
  从上面的分析来看,貌似没有问题。但是仔细分析不难发现缺陷所在,在前面的处理过程中存在一个隐患窗口期
  如果,在微服务A投递事件的时候,消息代理可能已经处理成功,但是响应的时候却出现网络异常,导致微服务A判定事件发布失败,从而回滚数据。最终的结果是事件被投递,数据库却被回滚。
Here Insert Picture Description

  在事件投递完成和数据库进行提交操作之间,如果微服务A宕机,也将造成数据库操作因为连接异常关闭而被回滚。最终的结果还是事件被投递,数据库却被回滚。
Here Insert Picture Description

  这个实现往往运行很长事件都不会出现问题,但是一旦出现问题便会很难发现问题所在。

本地事件表

  本地消息事件表方法将事件和业务数据保存在同一个数据库中,使用一个额外的事件恢复服务来恢复事件,有本地事务保证更新业务和发布事件的原子性。考虑到事件恢复可能会有一定的延时,所以服务在完成本地事务后可立即向消息代理发布一个事件,如下图所示:
Here Insert Picture Description
  本地事件表的说明如下:
1、微服务在同一个本地事务中记录业务数据和事件
2、当微服务实时发布一个事件时,立即通知关联的业务服务,如果事件发布成功则立即删除记录的事件。
3、事件恢复服务定时从本地事务表中恢复未发布成功的事件,并重新发布,直到重新发布成功时才删除记录的事件。
  其中操作 2 主要是为了增加发布事件的实时性,操作 3 是为了保证事件一定被发布。
  本地事件表方法的业务系统和事务系统耦合比较紧密,额外的数据库事件操作会给数据库带来压力,可能会成为数据库的性能瓶颈。
  思考:这里主要是为了保证事件一定被发布,这里应该可以通过重试事件发布直到成功为止,确保事件发布至少一次,同时实现事件消费的幂等性,最终保证数据操作和事件发布的原子性。

外部事件表

  外部事件表方法将事件持久化到外部的事件系统,事件系统需要提供实时事件消息服务以接收微服务发布的事件,同时事件系统还需要提供事件恢复服务来确认和恢复事件,如下图所示:
Here Insert Picture Description
  外部事件表的说明如下:
1、业务服务在事务提交前进行,通过实时事件服务事件服务系统请求发送事件,事件系统只记录事件并不真正发送。
2、业务服务提交后,通过实时事件服务向事件系统确认事件需要被成功发送,确认“事件需要被成功发送”后事件系统才真正将事件发布到消息代理中。
3、业务服务在业务回滚时,通过实时事件服务取消事件系统中的事件。
4、如果业务服务在发送确认或取消之前停止了服务怎么办?事件系统的事件恢复服务会定期找到未确认发送的事件,并向业务服务查询事件状态,根据业务服务返回的状态决定事件是发布还是取消。该方法将业务系统和事件系统独立解耦,使它们可以独立伸缩。但是,这种方式需要一次额外的发送操作,并且需要发布者提供额外的查询接口。

2 业务补偿模式

  为了方便描述业务补偿模式(以下简称补偿模式),这里先定义如下两个概念。
业务异常:业务逻辑产生错误的情况,如账户余额不足、商品库存不足等。
技术异常:非业务逻辑产生的异常,如网络连接异常、网络超时等。
  补偿模式使用一个额外的协调服务(补偿框架)来协调各个需要保证一致性的微服务,协调服务按顺序调用各个服务,如果某个微服务调用异常(包括业务异常和技术异常),则取消之前所有已经调用成功的微服务。
  建议将补偿模式用于不能避免出现业务异常的情况,尽量通过优化业务模式的方式避免要求补偿事务。如此,账户余额不足的业务异常可以通过预先冻结金额的方式避免,商品库存不足可以通过要求商家准备额外的库存来解决,等等。
  我们通过一个例子来说明补偿模式。一家旅行公司提供预订行程的业务,可以通过公司的网站预订飞机票、火车票、酒店等。客户提交旅行订单后,旅行公司的预订形成业务开始按顺序串联调用航班预订服务、酒店预订服务、火车预订服务。直到最后的火车预订服务成功后,整个预订业务才算完成。如下图所示:
Here Insert Picture Description
  如果火车预订服务没有调用成功,那么之前预订的航班、酒店都要取消。取消之前预订的酒店、航班即为补偿过程。如下图所示:
Here Insert Picture Description
  为了降低开发的复杂性和提高效率,将协调服务实现为一个通用的补偿框架。补偿框架提供服务编排和自动完成补偿的功能。
  要实现补偿过程,我们需要做到如下两点
  首先,要确定失败的步骤和状态,从而确定要补偿的范围,在上面的例子中,我们不仅需要知道步骤3(预订火车)失败了,还要知道失败的原因。如果是因为预订火车服务返回无票,那么补偿过程只需要取消前两个步骤就可以了;但是如果失败的原因是因为网络超时,那么补偿过程除了取消前两个步骤外,还需要包括取消步骤3。
  其次,要能提供补偿操作使用到的业务数据。
  做到上面两点的办法是记录完整的业务流水,可以挺过业务流水的状态来确定需要补偿的步骤,同时业务流水可以为补偿提供需要的业务数据。
  业务补偿模式需要应对的难点:
1、预先知道微服务需要记录的业务数据是不可能的,因此需要通过框架表记录关键的业务数据key,同时还要定义如何根据业务数据key查询业务数据详情的方式,实现这样的通用能力并非易事。
2、补偿过程作为一个服务调用过程,同样存在调用不成功的情况,这时需要通过重试机制来保证补偿的成功。如果失败的原因不是暂时性的,即使重试也无法执行成功,这时需要终止重试。如果失败的原因是一些罕见的异常,比如网络异常,可以立即重试。。如果失败的原因是系统繁忙,例如超时等,可以等待一段时间再重试。重试操作一般会指定重试次数上限,如果重试次数达到了上限就不会再进行重试了,这时应该通过某种手段通知相关人员进行处理。对于等待重试策略,如果重试时任然出现错误,那么可以主键增加等待时间,知道达到一个上限,以上限作为等待时间。如果某个时刻聚集了大量请求重试的操作,那么补偿框架需要控制重试请求重试的流量,比防止对工作服务造成过大的压力。
  业务补偿模式的建议:
1、微服务模式下,实现补偿操作不是简单地回退到业务发生时的状态,因为可能还有其他并发请求同时更改了状态,一般都需要逆操作的方式进行补偿。
2、补偿过程不需要严格按照与业务发生相反的顺序执行,可以依据工作服务的重要程度优先执行,甚至可以并发执行。
3、有些服务的补偿过程是由依赖关系的,如果被依赖的服务的补偿操作没有执行成功,那么就要及时终止补偿过程。

3 TCC(Try-Confirm-Cancel)模式

  一个完整的TCC业务由一个主业务服务和若干个从业务服务组成,主业务服务发起并完成整个业务服务。TCC模式要求服务提供三个接口:Try、Confirm、Cancel,如下图所示
Here Insert Picture Description
Try:完成所有业务检查,预留必要的业务资源。
Confirm:真正执行业务的接口,不做任何业务检查,只使用Try阶段预留的业务资源,其操作满足幂等性。
Cancel:释放Try阶段预留的业务资源,其操作满足幂等性。
  整个TCC业务分成两个阶段完成,如下图所示
  第一个阶段:主业务服务分别调用所有从业务服务的Try操作,并在活动管理器中登记所有从业务操作。当所有从业务服务的Try操作都调用成功或者某个从业务服务的Try操作失败时,进入第二阶段。
  第二阶段:活动管理器根据第一阶段执行结果来执行Confirm或Cancel操作。如果第一阶段的所有Try操作都调用成功,则活动管理器调用所有从业务活动的Confirm操作,否则调用所有从业务服务的Cancel操作。

Here Insert Picture Description

  Note that, Confirm and Cancel the second phase of the operation itself but also to meet the eventual consistency of the process, when calling Confirm or Cancel may also call fails for some reason, all activities need management support capability retry, At the same time and also requires Confirm Cancel idempotent operations.

VS TCC mode compensation mode

  A compensation mode of the defect is not obvious isolation. Starting with the first service step until all work is completed the service (or the compensation process is complete), it is inconsistent with other services visible. In addition, eventual consistency guarantees also fully dependent on the robustness of the service coordination, service coordination abnormal if there is no way to achieve consistency.
  TCC mode to some extent make up for these shortcomings. In TCC mode, from start to Confirm operation, all business operations are isolated (guaranteed by the operational level). In addition, the service can work, take the initiative to set aside resources for business operations by specifying Try Cancel operation timeout in order to achieve self-government micro-services.
  TCC mode and the compensation mode as the need for coordination and service work services, service coordination can be achieved as a universal service for the general mine construction. The difference is that the compensation mode, the TCC service framework necessary to record detailed operational flow, and complete operational elements Confirm Cancel service operated by the service provider .
Original "architecture book"
https://www.docin.com/p-1810236935.html

Published 88 original articles · won praise 317 · Views 350,000 +

Guess you like

Origin blog.csdn.net/sunxianghuang/article/details/103020275