博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分布式系统事务一致性解决方案
阅读量:4312 次
发布时间:2019-06-06

本文共 1162 字,大约阅读时间需要 3 分钟。

背景:

在 OLTP 系统领域,我们在很多业务场景下都会面临事务一致性方面的需求。

经典问题:A给B转账,需要扣A再加B。其中任何一步出现问题都需要回滚。

再现实业务场景中可能还涉及三个甚至更多业务模块交互。

相关知识:CAP定律,BASE理论等。

思路,不存在绝对的一致性,需要在业务允许的范围内,通过最终一致性解决。

 

方法一:二段(三段)提交

 

总结:这种方式实现难度不算太高,比较适合传统的单体应用,在同一个方法中存在跨库操作的情况。但分布式事务对性能的影响会比较大,不适合高并发和高性能要求的场景。

 

方法二:提供回滚接口

顾名思义,由依赖模块方提供回滚接口。

总结:这种方式缺点比较多,通常在复杂场景下是不推荐使用的,除非是非常简单的场景,非常容易提供回滚,而且依赖的服务也非常少的情况。 

这种实现方式会造成代码量庞大,耦合性高。而且非常有局限性,因为有很多的业务是无法很简单的实现回滚的,如果串行的服务(A->B->C)很多,回滚的成本实在太高。

 

方法三:本地消息表

ebay的经典解决思路,通过本地消息表存储,通过MQ通知依赖方,依赖方自己保证数据正常消费(幂等,补偿)

总结:这种方式比较常见,如果 MQ自身和业务都具有高可用性,理论上是可以满足大部分的业务场景的。不过在没有充分测试的情况下,不建议在交易业务中直接使用。 

 

方法四:MQ(事务消息)

下面以阿里巴巴的 RocketMQ 中间件为例,分析下其设计和实现思路。

RocketMQ 第一阶段发送 Prepared 消息时,会拿到消息的地址,第二阶段执行本地事物,第三阶段通过第一阶段拿到的地址去访问消息,并修改状态。细心的读者可能又发现问题了,如果确认消息发送失败了怎么办?RocketMQ 会定期扫描消息集群中的事物消息,这时候发现了 Prepared 消息,它会向消息发送者确认,Bob 的钱到底是减了还是没减呢?如果减了是回滚还是继续发送确认消息呢?RocketMQ 会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就保证了消息发送与本地事务同时成功或同时失败。如下图:

 

总结:据笔者的了解,各大知名的电商平台和互联网公司,几乎都是采用类似的设计思路来实现“最终一致性”的。这种方式适合的业务场景广泛,而且比较可靠。不过这种方式技术实现的难度比较大。目前主流的开源 MQ(ActiveMQ、RabbitMQ、Kafka)均未实现对事务消息的支持,所以需二次开发或者新造轮子。比较遗憾的是,RocketMQ 事务消息部分的代码也并未开源,需要自己去实现。 

 

其他补偿方法

加日志  》》扫描日志  》》程序补偿  》》人工补偿

 

参考地址:

转载于:https://www.cnblogs.com/strive-x/p/10305173.html

你可能感兴趣的文章
<Bootstrap> 学习笔记六. 栅格系统使用案例
查看>>
vector--C++ STL 学习
查看>>
蜕变成蝶~Linux设备驱动之异步通知和异步I/O
查看>>
jquery简单开始
查看>>
作业2
查看>>
ios上架报错90080,90087,90209,90125 解决办法
查看>>
给button添加UAC的小盾牌图标
查看>>
如何退出 vim
查看>>
Robberies
查看>>
get post 提交
查看>>
R安装
查看>>
JavaScript高级特性-实现继承的七种方式
查看>>
20121016学习笔记四
查看>>
EntityFramework 学习 一 Stored Procedure
查看>>
Sliverlight之 故事板
查看>>
Java 必知必会的 20 种常用类库和 API
查看>>
HDU 1087 Super Jumping! Jumping! Jumping!
查看>>
0007_初始模块和字节码
查看>>
[效率提升]如何管理好你的电脑文件
查看>>
C++实验二
查看>>