本文内容
- 什么是分布式事务
- 分布式事务中的难点
- 常见的解决方案
- 讲解经过可靠消息来解决分布式事务
什么是分布式事务?
有这样一个需求:数据库
小明有两个帐户,分别位于A、B两个数据库中,小明须要将A中的资金转到B中。微信
咱们如何实现?网络
按照下面的方式实现看看有没有问题。并发
- 链接数据库A,获取connA链接
- connA打开事务
- A库资金减小100
- 链接库B,获取connB链接
- connB打开事务
- B库资金增长100
- connA.commit()
- connB.commit()
上面操做,正常状况是没有问题。异步
考虑以下状况:分布式
第7步执行成功以后,网络出问题了,第8步会提交失败,此时的结果是:A库资金减小了100,B库资金却没有增长;这是一个网络问题致使了咱们业务失败了,网络因素是程序不可控的一些因素,还有其余的好比运行到7以后,系统忽然断电了,也会出现一样的结果。形成了数据错误,对业务影响也是比较大的。微服务
分布式事务能够这么理解:一个业务操做中,会包含不少子业务的,每一个子业务都是独立的事务,咱们须要考虑的是如何保证这些子业务都成功,或者都失败。blog
分布式事务中的难点
- 分布式事务中,分支多是各类各样的,可能存在各类异常状况致使有些成功有些却失败了,这些状况须要咱们程序可以处理,保证全部的分支要么都成功、要么都失败,不能出现部分红功而部分失败的状况。
- 分布式事务中,很难保证多个分支同时成功。每一个分支可能都是提供远程接口进行调用,之间存在网络故障的问题,前面的分支调用成功了,可是其余分支因为网络等不可控的因素而调用不成功,此时数据是很难作到同时一致性的。
- 实时一致性难以保证。那么咱们能够作到最终一致性也是能够的。
什么是最终一致性?
就拿上面的转帐来讲,A库的资金减小了,因为网络问题,操做B库的connB链接断开了,致使B库资金没有增长;网络问题是能够恢复了,若是网络恢复了,系统可以给B中资金加上,这样最终数据也是正确的;这中间有段时间AB库的资金是不一致的(A库减小了100,B库应该增长100却没有增长,数据是不一致的),可是最终某个时间点数据变为一致了。可以将不一致的时间降到最低是系统须要考虑的问题。接口
分布式事务中,咱们能够接受数据在某个时间段以内不一致,可是数据最终在某个时间点是一致的。图片
常看法决方案
- 可靠消息模式
- TCC模式实现
分布式事务系列中主要讲这2种方案,这两种方案基本上能够解决大多数常见的分布式事务的问题,因此我们必须把这两种方式拿下。
下面咱们介绍一下使用可靠消息如何实现?
可靠消息模式实现转帐操做

两个微服务
服务A:用于操做A库中的帐户
服务B:用于操做B库中的帐户
两个服务都是连接独立的数据库,依靠数据库提供的功能,可以保证各自的事务。
对于用户来讲过程以下:
- 调用服务A,扣款100
- 发送扣款成功的消息到消息服务
- 返回用户转帐已受理
接着
- 服务B,拉取到转帐消息
- B库中给帐户+100
- 调用消息服务将消息删除
- 服务B消费的过程当中,好比出现网络、机器重启等缘由,致使消费失败,等机器恢复以后,能够再次消费这条消息,重试屡次最终会成功
上面整个转帐过程当中有几点咱们须要考虑一下:
- 如何确保A服务中扣款成功以后,消息必定可以发送成功;若是消息发送失败而丢失了,后面的业务将无法进行。这块涉及如何发送可靠消息,以前消息系列的文章有介绍,你们能够看一下:聊聊业务系统中投递消息到mq的几种方式
- 咱们的服务通常都是集群的方式,消息消费的时候,可能会出现一条消息并发消费的状况,并发状况发生的时候,如何确保消费只可以被消费成功一次。若是一条转帐消息被成功消费两次,最终B帐户中将增长200,致使业务出错。这块能够参考如何保证消息消费的幂等性,这块以前也有讲过,你们也能够看一下:探讨一下实现幂等性的几种方式
依靠消息模式实现分布式事物,比较适合消费者必定会处理成功的场景。好比用户注册发送邮件、发送短信、送积分等。
总结
- 本文主要介绍了什么是分布式事务、其中的一些难点
- 常见的使用最多的解决方案:异步消息处理分布式事物、tcc模式
- tcc模式咱们在后面的文章中介绍,目前在咱们本身的系统中实现了通用的tcc,已经上线运行,运行也比较稳定
- 对分布式事务有兴趣、或有疑问的,能够加我微信itsoku交流
能够关注公众号:路人甲Java,获取年薪50万课程,获取最新文章。
