分布式事务【整理、总结】
分布式事务的核心其实是维护分布式数据资源(DB、缓存、MQ等)的一致性。
CAP理论
C:一致性;A:可用性;P:分区容错性
CAP不可能同时满足,在分布式系统中P不能放弃(也就是分布式系统部分实例出错的情况下,仍然可以对外提供服务),因此只能选择CP或者AP。
选择CP:刚性事务,如XA的2PC、3PC;
选择AP:基于BASE理论实现最终一致性,如TCC、基于MQ、尽最大努力通知;
2PC、3PC是数据库层面,不是业务代码层面,适合单体应用,同时访问多个数据库的情况,但是微服务的大背景下,基本不会允许这种情况的出现。由于效率低,不适合高并发场景。
2PC的优点是简单、易实现,缺点是:阻塞式的占用资源时间过久、协调者单点故障问题、数据不一致问题(部分commit请求丢失)。
3PC在2PC的基础上增加了一个阶段,并且增加了参与者的等待超时时间,但是并没有解决极端情况下数据不一致的问题。
TCC
Try、Confirm、Cancel;业务代码层面实现分布式事务。对代码的侵入性强,核心思想是针对每个操作都要实现对应的确认和补偿操作。实现复杂、不易维护。
跟钱打交道的场景,比如电商平台订单系统、支付、交易、转账等场景,大家都会用TCC方案,保证要么所有操作都成功,要么都回滚。
Try:业务系统做资源检测并锁住资源。比如常见的下单,在try阶段,我们不是真正的减库存,而是把下单的库存给锁定住。
Confirm:所有的Try操作都成功了,执行Confirm操作,也就是执行具体的业务,然后释放占有的资源。
Cancel:至少一个Try失败,执行Cancel操作,释放资源。
注意事项:
1. Try操作、Confirm操作和Cancel操作需要满足幂等性,允许失败重试;通常我们通过事务id或者业务主键ID判重来实现;
2. Try操作失败了可以Cancel,那么Confirm和Cancel失败了怎么办?
TCC中会添加失败日志,失败后进行重试,如果重试后仍然失败,就人工介入进行恢复和处理。
Java生态一般使用成熟的现成方案Seata。
TCC以银行转账做示例:
基于MQ的异步通知解决方案
RocketMQ通过half消息支持分布式事务,Kafka和RabbitMq也都支持此类方案。
适用于对数据的实时性要求不高的场景,主要用于内部系统的数据最终一致性保证。使用此方案最好可以有check或者对账流程进行兜底。
最大努力通知
主要用于外部系统的数据一致性保证,因为外部网络环境更加复杂和不可信。比如支付平台和商家等跨网络对接。
在MQ方案的基础上增加了如下操作:
业务主动方完成业务操作后,发送MQ消息,通过消息订阅方(内部系统)调用业务被动方(外部系统)的接口发送事务消息。如果失败则根据重试规则进行消息重新投递;
业务主动方提供查询接口,供业务被动方进行主动查询,恢复丢失的事务消息。
参考资料
分布式事务 (秒懂)_51CTO博客_分布式事务xa
分布式事务-CSDN博客
五种分布式事务解决方案(图文总结) - Hello-Brand - 博客园