分布式事务解决方案

68 阅读2分钟

先看这里
seata官网: seata.io/zh-cn/docs/…

2pc和3pc的区别?假设出现分区问题,怎么解决?具体怎么实现2pc

juejin.cn/post/684490…
2阶段的问题:
问题1:性能问题。在阶段1,锁定资源之后,要等所有节点返回,然后才能一起进入阶段2,不能很好地应对高并发场景。
问题2:阶段1完成之后,如果在阶段2事务协调者宕机,则所有的参与者接收不到Commit或Rollback指令,将处于“悬而不决”状态。
问题3:阶段1完成之后,在阶段2,事务协调者向所有的参与者发送了Commit指令,但其中一个参与者超时或出错了(没有正确返回ACK),则其他参与者提交还是回滚呢?也不能确定。”

3pc: 1:第一阶段不阻塞;
2.第二阶段引入参与者超时,如果第二阶段参与者超时默认回滚;
3.第三阶段如果参与者超时,默认commit,第三阶段如果协调者有收到参与者失败响应则发送回滚,如果超时未收到某些参与者,那就默认commit。 所以可能会导致最终数据不一致。

二阶段提交的实现-AT模式

TCC的实现方案

相比于2pc,在第二阶段如果失败,则一直重试,不管是commit还是cancel

最终一致性方案,MQ+对账/事务MQ

SAGA两种恢复方案

Saga的执行顺序有两种:

T1, T2, T3, ..., Tn

T1, T2, ..., Tj, Cj,..., C2, C1,其中0 < j < n Saga定义了两种恢复策略:

向后恢复,即上面提到的第二种执行顺序,其中j是发生错误的sub-transaction,这种做法的效果是撤销掉之前所有成功的sub-transation,使得整个Saga的执行结果撤销。 向前恢复,适用于必须要成功的场景,执行顺序是类似于这样的:T1, T2, ..., Tj(失败), Tj(重试),..., Tn,其中j是发生错误的sub-transaction。该情况下不需要Ci。
一般重试可以通过消息队列重试,如果重试超过了多少次数则报警到群里或者有其他补偿接口,报警到群里可以人工介入处理,一般都不是业务代码的问题,可能是服务状态或者网络问题,重试几次就好了。

实践案例

订单状态更改->司机状态更改

司机状态更改失败(网络超时或者服务报错),再次查询一次司机状态,还是不行就转MQ异步重试,这是因为订单状态回滚成本比较高,订单状态更改耦合了一些业务逻辑在里面。

并发问题处理:
多订单同时圈选到同一个司机,司机加锁,然后再是订单状态更改-司机状态更改
多引擎同时对一个订单派不同的司机,订单锁通过mysql的CAS实现

提高系统吞吐量的手段:缓存+异步 司机抢单流程:多个司机同时抢一个订单