分布式事务

本地事务ACID

原子性(Atomicity):Undolog
隔离性(Isolation):4种隔离级别+mvcc
持久性(durability):Redolog+刷盘
一致性(Consistency):以上AID一起保证C

CAP

Consistency (一致性)
Availability (可用性)
Partition Tolerance (分区容错性)

CAP原则
分布式系统不能同时支持 CAP需要根据自己的实际业务需求选择CAP的其中两个。
CP:Zookeeper
AP:Eureka
Nacos既支持CP也支持AP,可配置
CP目前在大多数人看来是一个错误方向,强一致性实现非常困难且不合理,主流走向几乎都是认为保证可用性更为重要。

BASE理论

即使无法做到强一致性,但每个应用都可以根据自身业务特点采用适当的方式来使系统达到最终一致性。
基本可用(Basically Available):响应时间可能会增加,保证核心服务(降级思想)
软状态(Soft state):数据同步允许一定时间的延迟
最终一致性(Eventually consistent):非实时,所有数据保证最终一致

分布式事务

要达成一致性需要满足AID,还要受到AP牵制Availability(可用性)+Partition tolerance(分区容错性)

目前市面常见分布式事务解决方案
同步:2PC,tcc,saga,seata(xa/at/tcc/saga)
异步:可靠性投递:mq事务消息,本地事务消息

同步与异步不是互斥方案,一般会混合采用
同步选择:核心链路采用同步,如任务完成后,同步处理单据,库存,异步处理非核心数据

同步方案

2PC
--XA协议(Automikos/seata)
1阶段prepare
2阶段commit/rollback
两个阶段完全同步,性能极其差,强一致性

--2.seata AT模式
1阶段:
全局锁for update
业务数据+seata回滚sql----本地事务commit
释放全局锁
2阶段异步commit/rollback
commit则删除seata回滚sql数据 rollback则根据回滚sql回滚

AT模式2阶段异步化提升了性能,不过会带来可见性问题,可能数据会被非seata管理变更,数据订正可能会踩坑,另外注意seata隔离级别是read uncommited
AT模式适用于一些非核心场景,快速接入分布式事务,无业务侵入

TCC
TCC也可以对应XA的prepare,commit,cancel,只不过tcc基于业务实现

try保证资源锁定;包括但不限于添加预占字段预占方式
commit与cancel必须保证成功,即这里需要有重试机制,即为了优化性能,cc在业务内部可以做成异步

举例:
订单中心使用TCC调用库存中心
try占用库存成功后,confirm扣减库存/cancel释放库存,库存中心confirm/cancel内部可以异步,保证cc成功即可

TCC模式适用于较为核心的场景,做定制开发,对业务整体流程把控比较严格

Saga
Saga事务将TCC的前面两步合并为一步,减少try锁定的性能问题,不过其对应每个动作有对应的补偿事件,如回滚

saga使用于业务流程长如状态机处理场景,做各个状态补偿机制,不过saga模式由于各个阶段直接提交,无法保证隔离性

异步

异步分布式事务的思想就是做可靠性投递,保证消息可以投递到消费者

1.本地消息表+补偿
本地消息与业务数据保证同事务
正向补偿,由业务定时任务来进行“check补偿”,定时任务check逻辑由发送方保证,后决定是否投递该消息,消费者要保证重试幂等
逆向补偿,取消、告警等
坏处:消息表耦合到业务域,如果解决方案不够优良,可能会产生很多杂活

2.事务消息、rabbitmq确认机制
利用现有中间件,如rocketmq事务消息,rabbitmq确认机制来实现可靠性投递,减少业务代码

举例:
电商下单场景,首先要区分发起者与参与者有哪些
发起者:订单模块,参与者:库存模块,商品模块,营销模块,用户中心模块
其次区分核心与非核心流程
如订单,库存包含核心数据流转;商品,营销,用户没有核心数据流转属于非核心
核心流程同步事务,非核心流程异步事务

小结:

分布式事务是一个大课题,每个方案都有各自的优点和局限性,针对我们的业务场景,做对应的业务解决方案,要对当前业务的倾向性有自己的判断,不要盲目确定方案。牢记:数据乱了,就是大事故;
除了分布式事务外,一定要做“对账”来保证数据的正确性一致性。

其他

空回滚,防悬挂
对于分布式事务来说,一阶段的数据如果还未落地,此时收到了二阶段的回滚请求,那么其实是一个二阶段空回滚
参与者回滚之后,之前超时的一阶段请求到达(一阶段请求包没有丢,只是由于网络延迟,晚于二阶段回滚到达),此时参与者如果按照一个正常的一阶段请求处理,那么接下来将永远不会收到二阶段请求,出现事务悬挂;

故参与者在设计时,需要考虑如何防止出现这种悬挂;通常的做法是一阶段请求执行前,判断当前参与者有无执行过空回归,无则正常执行一阶段,有则返回一阶段失败;
防悬挂出现几率低,可以做监控告警处理

你可能感兴趣的:(分布式事务)