转自:https://mp.weixin.qq.com/s?__biz=MzI5MDEzMzg5Nw==&mid=2660392948&idx=1&sn=11602f1258af8bbf88322558aa8a2f21&scene=1&srcid=0805vjamp1Rnj59pDI9DfIUS&key=8dcebf9e179c9f3afab76dc59d913c0ab919bf3f6413ec4b70dc2b3e41f799929664a4972369f2a2952f1b3edc3d99fd&ascene=0&uin=NjEyNTQwNjQx&devicetype=iMac+MacBookPro11%2C1+OSX+OSX+10.11.6+build(15G31)&version=11020113&pass_ticket=tUiG9aJFHStrqSDgcrh4%2BZJlPoFtEgMjXnnAAp4HybEzxggzmpu2VrW%2BIEMPXXCX
转载本文需注明出处:EAII企业架构创新研究院,违者必究。如需加入微信群参与微课堂、架构设计与讨论直播请直接回复此公众号:“加群 姓名 公司 职位 微信号”。
『微信后台回复“一致性”,获取系列完整PPT下载』
· · ·
大家好
今天分享的还是关于微服务架构下的数据一致性保证的话题,是数据一致性系列分享的第三篇。
在第一篇分享中介绍了微服务架构应满足数据最终一致性,并简要介绍了最终一致性的三种模式:可靠事件模式、补偿模式、TCC模式。
在第二篇分享中深入可靠事件模式,讲述了可靠事件投递和幂等性的实现方式和需要注意的问题。
在今天的第三篇分享中来谈谈补偿模式和TCC模式,主要从三个方面来谈。
· · ·
首先简单回顾一下补偿模式。
补偿模式使用一个额外的协调服务来协调各个需要保证一致性的微服务(我们称为工作服务),协调服务按顺序调用各个工作服务,如果某个工作服务调用失败就撤销之前所有已经完成的工作服务。要求需要保证一致性的工作服务提供补偿操作。
比如一家旅行公司通过协调3种工作服务为客户预订航班、预订酒店和预订火车。
当其中的预订火车失败时,就需要取消之前的航班和酒店的预订,这里面包含的三个工作服务都需要提供补偿操作。
为了降低开发的复杂性和提高效率,协调服务实现为一个通用的补偿框架。补偿框架提供服务编排和自动完成补偿的能力。
· · ·
第一部分:实现补偿模式的关键在于业务流水的记录
要实现补偿过程,我们需要做到两点
首先要确定失败的步骤和状态,从而确定需要补偿的范围。
在上面的例子中我们不光要知道第3个步骤(预订火车)失败,还要知道失败的原因。如果是因为预订火车服务返回无票,那么补偿过程只需要取消前两个步骤就可以了;但是如果失败的原因是因为网络超时,那么补偿过程除前两个步骤之外还需要包括第3个步骤。
其次要能提供补偿操作使用到的业务数据。
比如一个支付微服务的补偿操作要求参数包括支付时的业务流水id、账号和金额。理论上说实际完成补偿操作可以根据唯一的业务流水id就可以,但是提供更多的要素有益于微服务的健壮性,微服务在收到补偿操作的时候可以做业务的检查,比如检查账户是否相等,金额是否一致等等。
做到上面两点的办法是记录完整的业务流水,可以通过业务流水的状态来确定需要补偿的步骤,同时业务流水为补偿操作提供需要的业务数据。
当客户的一个预订请求达到时,协调服务(补偿框架)为请求生成一个全局唯一的业务流水号。并在调用各个工作服务的同时记录完整的状态。
1.记录调用bookFlight的业务流水,调用bookFlight服务,更新业务流水状态
2.记录调用bookHotel的业务流水,调用bookHotel服务,更新业务流水状态
3.记录调用bookTrain的业务流水,调用bookTrain服务,更新业务流水状态
当调用某个服务出现异常时,比如第3步骤(预订火车)异常。
协调服务(补偿框架)同样会记录第3步的状态,同时会另外记录一条事件,说明业务出现了异常。然后就是执行补偿过程了,可以从业务流水的状态中知道补偿的范围,补偿过程中需要的业务数据从记录的业务流水中获取。
对于一个通用的补偿框架来说,预先知道微服务需要记录的业务要素是不可能的。那么就需要一种方法来保证业务流水的可扩展性,这里介绍两种方法:大表和关联表。
大表顾明思议就是设计时除必须的字段外,还需要预留大量的备用字段,框架可以提供辅助工具来帮助将业务数据映射到备用字段中。
关联表,分为框架表和业务表,技术表中保存为实现补偿操作所需要的技术数据,业务表保存业务数据,通过在技术表中增加业务表名和业务表主键来建立和业务数据的关联。
大表对于框架层实现起来简单,但是也有一些难点,比如预留多少字段合适,每个字段又需要预留多少长度。另外一个难点是如果向从数据层面来查询数据,很难看出备用字段的业务含义,维护过程不友好。
关联表在业务要素上更灵活,能支持不同的业务类型记录不同的业务要素;但是对于框架实现上难度更高,另外每次查询都需要复杂的关联动作,性能方面会受影响。
有了上面的完整的流水记录,协调服务就可以根据工作服务的状态在异常时完成补偿过程。
· · ·
第二部分:通过重试来保证补偿过程的完整,从而满足最终一致性
补偿过程作为一个服务调用过程同样存在调用不成功的情况,这个时候需要通过重试的机制来保证补偿的成功率。当然这也就要求补偿操作本身具备幂等性。
关于幂等性的实现在上一篇分享中已经做过讨论,有兴趣的同学可以从普元官方下载。
如果只是一味的失败就立即重试会给工作服务造成不必要的压力,我们要根据服务执行失败的原因来选择不同的重试策略。
1)如果失败的原因不是暂时性的,由于业务因素导致(如业务要素检查失败)的业务错误,这类错误是不会重发就能自动恢复的,那么应该立即终止重试。
2)如果错误的原因是一些罕见的异常,比如因为网络传输过程出现数据丢失或者错误,应该立即再次重试,因为类似的错误一般很少会再次发生。
3)如果错误的原因是系统繁忙(比如http协议返回的500或者另外约定的返回码)或者超时,这个时候需要等待一些时间再重试。
重试操作一般会指定重试次数上线,如果重试次数达到了上限就不再进行重试了。这个时候应该通过一种手段通知相关人员进行处理。
对于等待重试的策略如果重试时仍然错误,可逐渐增加等待的时间,直到达到一个上限后,以上限作为等待时间。
如果某个时刻聚集了大量需要重试的操作,补偿框架需要控制请求的流量,以防止对工作服务造成过大的压力。
另外关于补偿模式还有几点补充说明
1.微服务实现补偿操作不是简单的回退到业务发生时的状态,因为可能还有其他的并发的请求同时更改了状态。一般都使用逆操作的方式完成补偿。
2.补偿过程不需要严格按照与业务发生的相反顺序执行,可以依据工作服务的重用程度优先执行,甚至是可以并发的执行。
3.有些服务的补偿过程是有依赖关系的,被依赖服务的补偿操作没有成功就要及时终止补偿过程。
4.如果在一个业务中包含的工作服务不是都提供了补偿操作,那我们编排服务时应该把提供补偿操作的服务放在前面,这样当后面的工作服务错误时还有机会补偿。
5.设计工作服务的补偿接口时应该以协调服务请求的业务要素作为条件,不要以工作服务的应答要素作为条件。因为还存在超时需要补偿的情况,这时补偿框架就没法提供补偿需要的业务要素。
· · ·
第三部分:TCC模式是优化的补偿模式。
在补偿模式中一个比较明显的缺陷是,没有隔离性。从第一个工作服务步骤开始一直到所有工作服务完成(或者补偿过程完成),不一致是对其他服务可见的。另外最终一致性的保证还充分的依赖了协调服务的健壮性,如果协调服务异常,就没法达到一致性。
TCC模式在一定程度上弥补了上述的缺陷,在TCC模式中直到明确的confirm动作,所有的业务操作都是隔离的(由业务层面保证)。另外工作服务可以通过指定try操作的超时时间,主动的cancel预留的业务资源,从而实现自治的微服务。
TCC模式和补偿模式一样需要需要有协调服务和工作服务,协调服务也可以作为通用服务一般实现为框架。与补偿模式不同的是TCC服务框架不需要记录详细的业务流水,完成confirm和cancel操作的业务要素由业务服务提供。
在第4步确认预订之前,订单只是pending状态,只有等到明确的confirm之后订单才生效。
如果3个服务中某个服务try操作失败,那么可以向TCC服务框架提交cancel,或者什么也不做由工作服务自己超时处理。
TCC模式也不能百分百保证一致性,如果业务服务向TCC服务框架提交confirm后,TCC服务框架向某个工作服务提交confirm失败(比如网络故障),那么就会出现不一致,一般称为heuristic exception。
需要说明的是为保证业务成功率,业务服务向TCC服务框架提交confirm以及TCC服务框架向工作服务提交confirm/cancel时都要支持重试,这也就要confirm/cancel的实现必须具有幂等性。如果业务服务向TCC服务框架提交confirm/cancel失败,不会导致不一致,因为服务最后都会超时而取消。
另外heuristic exception是不可杜绝的,但是可以通过设置合适的超时时间,以及重试频率和监控措施使得出现这个异常的可能性降低到很小。如果出现了heuristic exception是可以通过人工的手段补救的。
以上就是今天分享的全部内容,到此为止关于微服务架构下的数据一致性保证的系列分析全部结束。感谢大家的收听,由于本人能力有限,分享的内容难免有不精确的地方,欢迎随时指正。
再次感谢大家。
相关推荐
本文将深入探讨微服务架构下的数据一致性概念,以及相关的设计模式和解决方案。 首先,我们需要理解数据一致性的重要性。在传统的单体应用中,由于所有业务逻辑都在同一个进程中执行,数据一致性相对容易维护。但在...
传统应用中,本地事务通过ACID(原子性、一致性、隔离性、持久性)原则保证数据的一致性,但在微服务架构中,由于服务间的解耦和数据库的分散,这种方法不再适用。分布式事务,如两阶段提交(2PC)协议,虽然能解决...
本文档深入探讨了微服务架构下保证数据一致性的几种方法,特别是补偿模式与TCC模式的应用。 #### 补偿模式 补偿模式是一种通过记录业务流水并在发生异常时执行逆向操作来恢复系统状态的方法。它依赖于业务流水的...
在微服务系统架构下,通过介绍可靠事件模式、补偿模式、TCC模式来实现数据的最终一致性
从这些概念和模式中可以看出,微服务架构的数据一致性保证需要多种技术与策略的组合使用。对账、可靠事件模式和补偿模式是实现最终一致性的三种主要模式。这些策略必须根据业务需求、性能要求和可用性要求来选择和...
总之,微服务架构下的数据一致性方案涉及到服务拆分、分布式事务模型和具体的实现框架。Seata作为一个强大的工具,能够帮助开发者在微服务环境中解决复杂的数据一致性问题,确保业务逻辑的正确性和系统的稳定性。...
总的来说,微服务架构下的数据一致性需要通过理解分布式系统理论,结合实际业务场景,设计和实现灵活的事务管理和补偿机制来保证。这通常涉及到对事务模型的优化、状态追踪、异常处理策略以及合适的同步和异步通信...
【微服务架构下的数据一致性】 微服务架构已成为现代企业构建复杂业务系统的一种主流方式,它带来的优势包括单一职责、独立开发部署、功能复用以及更好的系统容错能力。然而,随着服务的拆分,数据一致性成为了一个...
在《微服务架构下的数据一致性:概念及相关模式》中介绍了在微服务中实现数据一致性的三种方式,包括可靠事件模式、业务补偿模式、TCC模式。本文重点说一下可靠事件投递。可靠事件模式属于事件驱动架构,微服务完成...
在复杂微服务架构中,确保...这些知识点共同构建了在复杂微服务架构下保证数据一致性的基础,涵盖了从服务设计、扩展策略到具体的技术选型和实施细节。理解并掌握这些概念对于构建高可用、高并发的分布式系统至关重要。
总结来说,微服务架构下的数据一致性是一个复杂而持续演进的领域。从2PC到SAGA、CQRS和Event Sourcing,每种方法都有其优缺点,适用于不同的场景。在实际开发中,需要根据业务需求和系统特性,灵活选择和组合这些...
在微服务架构中,事务一致性是一个至关重要的议题。随着服务的拆分,传统的单体应用中的本地事务已无法满足需求,分布式事务应运而生。本文将深入探讨微服务下的事务一致性,包括CAP理论、BASE理论,以及各种分布式...
快手可能探讨了如何利用分布式事务、事件驱动或补偿事务等方式来解决跨服务的数据一致性问题。 4. **容错机制**:包括故障隔离、超时控制、重试策略等,这些是提高系统稳定性的关键。快手可能分享了他们在实践中...
- 微服务架构下,不同服务可能依赖于不同的数据存储系统,增加了保证数据一致性的难度。 ##### 4.2 数据一致性解决方案 - **基于异步补偿的分布式事务**:通过记录业务调用链,并在出现异常时沿调用链反向执行补偿...
在微服务架构下,分布式事务处理模型需要能够满足微服务架构的需求,提供高可用性和最终一致性。 微服务架构下的分布式事务处理可以使用多种模型和技术来解决问题,如TCC模型、可靠消息模型和业务补偿模型等。这些...
### Fescar在微服务架构下分布式一致性的实践 #### 一、Fescar简介 Fescar是一款针对微服务架构设计的分布式事务解决方案,它致力于提供高效且易于使用的分布式事务处理能力。随着微服务架构的普及和发展,分布式...
- **数据一致性**:分布式系统中保持数据一致性的挑战,如使用分布式数据库或补偿事务。 - **监控与日志**:实施全面的监控和日志收集,以便快速定位和解决问题。 - **组织结构与文化**:需要匹配的敏捷开发团队...
分布式事务在微服务架构下是实现复杂业务逻辑的关键技术,因为微服务架构通常涉及多个独立的服务,这些服务可能需要在单个操作中保持数据的一致性。然而,由于服务之间的网络延迟、服务失败等问题,传统的单体应用中...