「轻阅读」分布式事务的四种解决方案,成长需要尝试

偷懒的程序员 2019-12-17 15:40:55 ⋅ 574 阅读

分布式事务指事务的操作位于不同的节点上,需要保证事务的 AICD 特性。

例如在下单场景下,库存和订单如果不在同一个节点上,就涉及分布式事务。

在分布式系统中,要实现分布式事务,无外乎那几种解决方案。

一、两阶段提交(2PC)

两阶段提交(Two-phase Commit,2PC),通过引入协调者(Coordinator)来协调参与者的行为,并最终决定这些参与者是否要真正执行事务。

1. 运行过程

1.1 准备阶段

协调者询问参与者事务是否执行成功,参与者发回事务执行结果。


1.2 提交阶段

如果事务在每个参与者上都执行成功,事务协调者发送通知让参与者提交事务;否则,协调者发送通知让参与者回滚事务。

需要注意的是,在准备阶段,参与者执行了事务,但是还未提交。只有在提交阶段接收到协调者发来的通知后,才进行提交或者回滚。


2. 存在的问题

2.1 同步阻塞 所有事务参与者在等待其它参与者响应的时候都处于同步阻塞状态,无法进行其它操作。

2.2 单点问题 协调者在 2PC 中起到非常大的作用,发生故障将会造成很大影响。特别是在阶段二发生故障,所有参与者会一直等待状态,无法完成其它操作。

2.3 数据不一致 在阶段二,如果协调者只发送了部分 Commit 消息,此时网络发生异常,那么只有部分参与者接收到 Commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致。

2.4 太过保守 任意一个节点失败就会导致整个事务失败,没有完善的容错机制。

另外推荐这篇:分布式事务不理解?一次给你讲清楚。

二、补偿事务(TCC)

TCC 其实就是采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:

  • Try 阶段主要是对业务系统做检测及资源预留

  • Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。

  • Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。

举个例子,假入 Bob 要向 Smith 转账,思路大概是:我们有一个本地方法,里面依次调用

  1. 首先在 Try 阶段,要先调用远程接口把 Smith 和 Bob 的钱给冻结起来。

  2. 在 Confirm 阶段,执行远程调用的转账的操作,转账成功进行解冻。

  3. 如果第2步执行成功,那么转账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法 (Cancel)。

优点: 跟2PC比起来,实现以及流程相对简单了一些,但数据的一致性比2PC也要差一些

缺点: 缺点还是比较明显的,在2,3步中都有可能失败。TCC属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用TCC不太好定义及处理。

三、本地消息表(异步确保)

本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性,并且使用了消息队列来保证最终一致性。

  1. 在分布式事务操作的一方完成写业务数据的操作之后向本地消息表发送一个消息,本地事务能保证这个消息一定会被写入本地消息表中。

  2. 之后将本地消息表中的消息转发到 Kafka 等消息队列中,如果转发成功则将消息从本地消息表中删除,否则继续重新转发。

  3. 在分布式事务操作的另一方从消息队列中读取一个消息,并执行消息中的操作。


优点: 一种非常经典的实现,避免了分布式事务,实现了最终一致性。

缺点: 消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。

四、MQ 事务消息

有一些第三方的MQ是支持事务消息的,比如RocketMQ,他们支持事务消息的方式也是类似于采用的二阶段提交,但是市面上一些主流的MQ都是不支持事务消息的,比如 RabbitMQ 和 Kafka 都不支持。

以阿里的 RocketMQ 中间件为例,其思路大致为:

第一阶段Prepared消息,会拿到消息的地址。第二阶段执行本地事务,第三阶段通过第一阶段拿到的地址去访问消息,并修改状态。

也就是说在业务方法内要想消息队列提交两次请求,一次发送消息和一次确认消息。如果确认消息发送失败了RocketMQ会定期扫描消息集群中的事务消息,这时候发现了Prepared消息,它会向消息发送者确认,所以生产方需要实现一个check接口,RocketMQ会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就保证了消息发送与本地事务同时成功或同时失败。

另外推荐这篇:分布式事务不理解?一次给你讲清楚。


优点: 实现了最终一致性,不需要依赖本地数据库事务。

缺点: 实现难度大,主流MQ不支持,RocketMQ事务消息部分代码也未开源。

通过本文我们总结并对比了几种分布式分解方案的优缺点,分布式事务本身是一个技术难题,是没有一种完美的方案应对所有场景的,具体还是要根据业务场景去抉择吧。笔者上家公司是试用阿里RocketMQ去实现的分布式事务,现在也有除了很多分布式事务的协调器,比如LCN等,大家可以多去尝试。



全部评论: 0

    我有话说:

    阅读」移动端事件穿透原理与解决方案

    本文将带你了解事件穿透及如何在实际项目中选择合适方案解决事件穿透问题。

    阅读」亿级用户分布式数据存储解决方案

    分布式数据库和分布式存储是分布式系统中难度最大、挑战最大,也是最容易出问题地方。互联网公司只有解决分布式数据存储问题,才能支撑更多次亿级用户涌入。

    高并发下分布式事务解决方案-MQ消息事务+最终一致性

    分布式事务分布式事务就是指事务参与者、支持事务服务器、资源服务器以及事务管理器分别位于不同分布式系统不同节点之上

    阅读」为什么在做微服务设计时候需要DDD?

    设计蓝图里为什么没有看到DDD影子呢?

    阅读」移动端适配必须掌握基本概念和适配方案

    随着技术发展,移动设备越来越流行,并且不同设备间屏幕尺寸和屏幕像素差异,移动端开发面临着多分辨率适配问题。

    阅读」图文并茂带你了解分布式架构演进

    初始阶段架构初始阶段 小型系统 应用程序、数据库、文件等所有资源都在一台服务器上通俗称LAMP

    阅读」Dubbo 如何成为连接异构微服务体系最佳服务开发框架

    要实现异构微服务体系间共存或迁移,关键点在打通异构体系间协议与服务发现,得益于 Dubbo 自身对多协议、多注册模型支持

    阅读」如何设计移动端屏适配方案

    在众多移动设备中,前端开发人员如何在不同屏幕大小,不同程度高清屏下去百分百还原设计稿,从来都不

    阅读」美团开源QPS压测结果近5w/s分布式ID生成器leaf调试实战

    大型互联网项目ID要保证全局唯一,一般不在用数据库自带id自增了,一般都会用分布式id生成器。

    「转载」分布式事务方案 - SAGA模式

    性能与架构:杜亦舒原文:https://mp.weixin.qq.com/s/An6QbAOw6jhWxg7GDT56Ug 本文目的是讲清楚 SAGA 这种分布式事务解决方案实现思路,不包括具体

    阅读」如何构建可伸缩Web应用?

    可伸缩性已经成为Web应用程序DNA!

    阅读」阿里云-开放平台高级技术家教你搭建微服务架构大金刚利器

    孔凡勇,花名云狄,阿里云-开放平台高级技术家,对高并发、高性能、高可用、可伸缩分布式系统架构设计有丰富经验,Cloud Native坚定拥护者,坚守开发一线打磨匠艺架构师。

    阅读」轻松理解 Kubernetes 核心概念

    Kubernetes 迅速成为云环境中软件部署和管理新标准。

    Java并发解决方案分布式应用限流实践

    任何限流都不是漫无目的,也不是一个开关就可以解决问题,常用限流算法有:令牌桶,漏桶。在之前文章中,也讲到过,但是那是基于单机场景来写。 之前文章:接口限流算法:漏桶算法&令牌桶算法

    阅读」Mysql调优你不得不知细节

    多数时候数据库会成为整个系统瓶颈

    阅读」推荐系统中信息增强小技巧

    实用推荐系统构建经验,如何进行信息增强。

    阅读」大众点评是如何分表分库

    原大众点评订单单表早就已经突破两百G,由于查询维度较多,即使加了两个从库,优化索引,仍然存在很多查询不理想

    阅读」“做完”和“做好”区别

    在工作中,“做完”和“做好”虽然仅一字之差,但前者只是完成了某项工作,而后者则不仅是完成了工作还有一个好