问题来自Java技术沙龙的陈启辉
Java线下沙龙报名链接:https://yq.aliyun.com/activity/796
最终都必须保证数据一致性,至于中间具体采用哪种模式,还是需要根据具体的业务逻辑来选择:
1、可靠事件模式
可靠事件模式属于事件驱动架构,当某件重要事情发生时,例如更新一个业务实体,微服务会向消息代理发布一个事件。消息代理会向订阅事件的微服务推送事件,当订阅这些事件的微服务接收此事件时,就可以完成自己的业务,也可能会引发更多的事件发布。
这个过程可能导致出现不一致的地方在于:某个微服务在更新了业务实体后发布事件却失败;虽然微服务发布事件成功,但是消息代理未能正确推送事件到订阅的微服务;接受事件的微服务重复消费了事件。
可靠事件模式在于保证可靠事件投递和避免重复消费,可靠事件投递定义为(a)每个服务原子性的业务操作和发布事件(b)消息代理确保事件传递至少一次。
避免重复消费要求服务实现幂等性,如支付服务不能因为重复收到事件而多次支付。
2、补偿模式
为了描述方便,这里先定义两个概念:
业务异常:业务逻辑产生错误的情况,比如账户余额不足、商品库存不足等。
技术异常:非业务逻辑产生的异常,如网络连接异常、网络超时等。
补偿模式使用一个额外的协调服务来协调各个需要保证一致性的微服务,协调服务按顺序调用各个微服务,如果某个微服务调用异常(包括业务异常和技术异常)就取消之前所有已经调用成功的微服务。
补偿模式建议仅用于不能避免出现业务异常的情况,如果有可能应该优化业务模式,以避免要求补偿事务。如账户余额不足的业务异常可通过预先冻结金额的方式避免,商品库存不足可要求商家准备额外的库存等。
我们通过一个实例来说明补偿模式,一家旅行公司提供预订行程的业务,可以通过公司的网站提前预订飞机票、火车票、酒店等。
假设一位客户规划的行程是,(1)上海-北京6月19日9点的某某航班,(2)某某酒店住宿3晚,(3)北京-上海6月22日17点火车。在客户提交行程后,旅行公司的预订行程业务按顺序串行的调用航班预订服务、酒店预订服务、火车预订服务。最后的火车预订服务成功后整个预订业务才算完成。
如果火车票预订服务没有调用成功,那么之前预订的航班、酒店都得取消。取消之前预订的酒店、航班即为补偿过程。
需要注意的是酒店的取消预订、航班的取消预订同样不能保证一定成功,所以补偿过程往往也同样需要实现最终一致性,需要保证取消服务至少被调用一次和取消服务必须实现幂等性。
我们应该尽可能通过设计避免采用补偿方式,比如上面的例子中,在预订火车票失败的时候可以提示客户更改其他的时间。
3、TCC模式(Try-Confirm-Cancel)
一个完整的TCC业务由一个主业务服务和若干个从业务服务组成,主业务服务发起并完成整个业务活动,TCC模式要求从服务提供三个接口:Try、Confirm、Cancel。
第一阶段:主业务服务分别调用所有从业务的try操作,并在活动管理器中登记所有从业务服务。当所有从业务服务的try操作都调用成功或者某个从业务服务的try操作失败,进入第二阶段。
第二阶段:活动管理器根据第一阶段的执行结果来执行confirm或cancel操作。如果第一阶段所有try操作都成功,则活动管理器调用所有从业务活动的confirm操作。否则调用所有从业务服务的cancel操作。
需要注意的是第二阶段confirm或cancel操作本身也是满足最终一致性的过程,在调用confirm或cancel的时候也可能因为某种原因(比如网络)导致调用失败,所以需要活动管理支持重试的能力,同时这也就要求confirm和cancel操作具有幂等性。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。