即时消息服务框架(iMSF)应用实例之分布式事务三阶段提交协议的实现
一,分布式事务简介
在当前互联网,大数据和人工智能的热潮中,传统企业也受到这一潮流的冲击,纷纷响应国家“互联网+”的战略号召,企业开始将越来越多的应用从公司内网迁移到云端和移动端,或者将之前孤立的IT系统联网整合,或者将原来厚重的企业应用拆分重组,独立成一个个轻量级的应用对外提供服务,这对传统的业务处理的数据一致性,带来了严重的挑战,我们已经身处一个分布式的计算环境,分布式事务的需求越来越普遍。
举一个例子,某行业电商网站经过几年的发展,业务数据累积越来越多,查询越来越慢。经过内部评审分析,认为系统的瓶颈就是数据库压力过大,如果要解决这问题,必须分表分库,比如将订单,商品,用户分布到不同的数据库去,但这样随之带来一个问题,原来处理业务的时候使用的是本地事务,分库后就需要使用分布式事务了。
那么应该如何实现分布式事务呢?
这里我们需要明确一点,并非数据库天然就是分布式的在执行操作的,事务都是在一个数据库实例上进行的,如果要执行一个分布式事务的操作,那么就需要协调多个分散的数据库上执行的事务操作。所以在分布式事务中,有2个概念:
l Distributed Transaction Resource Owner (简称DTR):
n --分布式事务资源服务器,拥有事务资源的服务器,如绝大部分关系数据库,一些消息队列,或者一些能够执行类似事务操作的应用。
l Distributed Transaction Coordinate Controller (简称DTC):
n --分布式事务协调控制器,它协调控制分布式事务环境中的事务资源服务器,发送指令给它们并且处理事务资源服务器返回的结果。
二,分布式事务的实现层面
在分布式事务的具体实现层面,可以在数据库层直接实现,也可以在应用服务层面实现。如果是在应用服务层面实现,本质上它也可能是调用本地的数据库事务。
下面是DTR与DTC的拓扑关系图:
基于关系数据库层面接口实现的分布式事务
基于数据库的分布式事务,一般在应用程序的数据层调用系统的分布式事务组件,应用程序执行本地事务的时候,先选举出一个分布式事务协调器,然后协调器来协调各个本地事务的执行。由于是在应用程序的数据层进行的调用,所以它对远程数据库的操作是在本地进程内的。如果你的应用部署在多台服务器上,那么在每一台操作数据库的应用服务器上都要安装运行分布式事务协调器服务。
基于应用服务层面实现的分布式事务
基于应用服务层面的分布式事务,是在应用服务层面进行的事务控制,它同样会有分布式事务协调控制器,和事务资源服务器。与基于数据库层面的分布式事务不同,事务的类型支持更广泛,比如消息队列访问,文件写入或者具有补偿操作的业务应用程序,都可以成为事务资源,并且不要求这些事务资源本身支持分布式事务。举个例子,事务资源A是Windows上的SQLSERVER数据库,事务B是Linux上的MySQL数据库,这时候事务B就没法使用Windows上的事务协调控制器MSDTC了。而基于服务层面的分布式事务,可以解决这个问题。
三,分布式事务的2阶段提交协议(2PC)
第一阶段(1PC):提交投票阶段
协调器向事务资源服务器发出 CanCommit 的是否可以提交事务的询问指令,事务资源服务器收到此指令后,准备好要提交的事务资源,再向协调器回复 YES;如果没有准备好,比如执行事务中的操作出现了错误,应该回复 NO.如果某DTR无法回复,DTC也认为该DTR的结果是NO.
第一阶段,全部回复为YES,代表各个事务资源服务器均已经准备好了提交。
第一阶段,事务资源服务器DTR-2回复为NO,如果DTC等待DTR-2超过设定时间都没有得到回复,或者DTR-2与DTC断开了连接,也认为DTR-2的结果是NO
第二阶段(2 PC):提交或终止阶段
协调器统计所有事物资源服务器的回复数量,如果全部回复为YES,则向所有事物资源服务器发出Commit指令,否则,发出Abort指令。资源服务器收到指令后,执行相应的操作。
二阶段提交事务的数据不一致问题
在第二阶段(2PC),如果DTR没有收到DTC的指令改怎么办呢?
如果等到超时都没有收到DTC的指令,DTR处于“可以提交”或者“不可以提交”的双重状态,也就是提交状态不可知。假设DTR1没有收到DTC的提交指令或者撤销指令,DTR1可以假设DTR2也不会收到指令,因为此时大概率是DTC宕机或者网络整体不良,那么DTR1最佳的做法是回滚事务。
但是,如果仅仅是DTR1受网络影响没有收到提交指令,而DTR2收到了提交指令,那么DTR1回滚事务,DTR2提交了事务,整个分布式事务就是失败的,数据发生了不一致。
因此,2阶段提交的分布式事务不是高可靠的分布式事务控制模型,需要在事务资源的提交环节做更多的验证,这便是3阶段提交的分布式事务。
不过,对于大部分系统,2阶段提交的分布式事务已经能够满足应用了,因为通常情况下,都是基于数据库应用层实现的分布式事务,并且各个事务资源节点都在同一个局域网内,发生网络不稳定的概率非常小,并且现在不少数据库都会做高可靠性的数据库集群,发生宕机的可能性也非常小,最终出现数据不一致的概率也就非常小了。
如果系统的应用环境不能满足上面说的任何一个条件,即分布式事务的控制不是在数据库应用层,子系统不在一个局域网,或者数据库没有做高可靠的集群,并且对于系统的事务一致性要求非常高,那么应该使用3阶段提交协议来实现分布式事务。
四,分布式事务的3阶段提交协议(3PC)
对2阶段提交协议的分析我们发现,2PC的事务提交阶段状态是不确定的,整个事务容易出现不一致的情况。所以,我们队2PC的提交阶段,进一步拆分成“预提交”阶段和提交阶段,增加事务提交状态的确认过程。
第一阶段(1PC):提交投票阶段
协调器向事务资源服务器发出 CanCommit 的是否可以提交事务的询问指令,事务资源服务器收到此指令后,准备好要提交的事务资源,再向协调器回复 YES;如果没有准备好,比如执行事务中的操作出现了错误,应该回复 NO.如果某DTR无法回复,DTC也认为该DTR的结果是NO.
该阶段的处理过程跟2阶段提交协议的第一阶段是一样的,处理流程图参考前面,此略。
第二阶段(2 PC):预提交或终止阶段
预提交事务
协调器(DTC)统计所有事务资源服务器(DTR)的回复数量,如果全部回复为YES,则向所有事物资源服务器发出PreCommit指令,否则,发出Abort指令。资源服务器收到指令后,执行相应的操作。
在第二阶段,如果DTR收到PreCommit指令,则向DTC回复ACK消息,表示收到了指令,准备提交,接着,进入第三阶段,等待最终的提交指令。
终止事务
在第二阶段,如果在第一阶段有节点异常,DTC发出撤销指令,DTR收到了撤销指令,那么它执行回滚本地事务的操作。如果由于网络原因,某个DTR一直等到超时都没有收到PreCommit指令,那么它执行Abort撤销指令,回滚本地事务。
第三阶段(3 PC):提交或终止阶段
提交分布式事务
协调器(DTC)统计所有事务资源服务器(DTR)在第二阶段的回复数量,如果全部回复为ACK,则向所有DTR发出Commit指令。DTR收到指令后,执行事务提交操作,并返回Commit Done消息,DTC收到此消息,结束整个分布式事务过程。
回滚分布式事务
协调器(DTC)统计所有事务资源服务器(DTR)在第二阶段的回复数量,如果未收到全部回复为ACK,则它认为有节点可能出现了网络故障,此节点没有收到PreCommit指令或者虽然收到了却没有回复ACK,测试DTC应该向所有DTR节点发出撤销指令。各DTR收到撤销指令后,回滚本地事务,然后回复消息,DTC完成本次事务过程。
三阶段提交事务也并不完美
考察第3阶段的提交分布式事务的情况,DTR1收到了Commit指令,但是由于网络原因,DTR2没有收到此指令,那么DTR2是提交本地事务还是回滚本地事务?
站在DTR2的角度,它在本阶段可能收到Commit指令,也可能收到Abort指令,那么它既可以提交本地事务也可以回滚本地事务,两种操作是不确定的,所以,3阶段提交协议,仍然不是完美的,不能百分之百保证数据的最终一致性。
既然3阶段提交协议仍然有不确定性,那么相比2阶段提交协议有什么意义呢?
仔细想下,DTR2已经进入第3阶段了,那么肯定其它DTR都进入了第3阶段,而进入第3阶段的前提是各DTR节点都收到过PreCommit指令,都是已经准备好提交只等最后的提交指令了,否则各节点在第二阶段应该收到撤销指令,不会再进入第三阶段。既然各DTR节点都进入了第三阶段,它们都准备好提交事务了,那么即使没有收到最终的Commit指令,DTC发出Commit指令也是大概率的。所以,从概率上讲,如果在第三阶段,DTR没有收到Abort撤销指令,也没收到Commit提交指令,那么它默认应该指向Commit指令,提交本地事务。相比第二阶段某DTR节点没有收到指令而认为应该收到PreCommit指令的概率,要大得多。
关于第三阶段没有收到指令而应该大概率执行Commit指令的问题,理解起来可能有点困难,我给同事讲的时候大部分同事也难以理解,可能是我表述的问题,大家有更好的解释方式,欢迎交流,不胜感激!
5,实现 3阶段提交的分布式事务
本文将介绍一个基于服务层面而不是数据库层面的,3阶段提交的分布式事务中间件的设计开发过程。这个中间件必须解决下面几个问题:
l 通信组件—分布式事务控制器(DTC),分布式事务资源服务器(DTR)都是独立的服务,这些服务部署在不同的通信节点,它们之间需要进行可靠的网络通信,因此通信组件是基础;
l 数据访问组件—提供基础的数据读写操作,并且能够操作本地事务。
l 服务组件—将DTC,DTR的功能代码编写为相应的SOA服务组件
l 关系数据库—具有事务功能的关系数据库,可以是嵌入式的本地数据库,比如SQLite,也可以是服务器客户机模式的网络数据库,比如SQLSERVER。
各组件的关系图如下:
PDF.NET的消息服务框架(MSF)具有开发服务组件基础的接口和一套消息通信组件,同时还有一个服务容器,可以承载本篇文章说的分布式事务控制器DTC,分布式事务资源服务DTR这些服务应用,同时PDF.NET还有一个强大的数据访问组件 PDF.NET SOD,下一篇文章,我们将来具体讨论基于MSF和SOD的3阶段分布式事务应用的实现过程,它的源码已经发布在 https://github.com/bluedoctor/MSF-DistTransExample ,大家可以先睹为快。
即时消息服务框架(iMSF)应用实例之分布式事务三阶段提交协议的实现的更多相关文章
- 使用“消息服务框架”(MSF)实现分布式事务的三阶段提交协议(电商创建订单的示例)
1,示例解决方案介绍 在上一篇 <消息服务框架(MSF)应用实例之分布式事务三阶段提交协议的实现>中,我们分析了分布式事务的三阶段提交协议的原理,现在我们来看看如何使用消息服务框架(MSF ...
- 消息服务框架(MSF)应用实例之分布式事务三阶段提交协议的实现
一,分布式事务简介 在当前互联网,大数据和人工智能的热潮中,传统企业也受到这一潮流的冲击,纷纷响应国家“互联网+”的战略号召,企业开始将越来越多的应用从公司内网迁移到云端和移动端,或者将之前孤立的IT ...
- “一切都是消息”--iMSF(即时消息服务框架)入门简介
“一切都是消息”--这是iMSF(即时消息服务框架)的设计哲学. MSF的名字是 Message Service Framework 的简称,由于目前框架主要功能在于处理即时(immediately) ...
- “一切都是消息”--iMSF(即时消息服务框架)之【发布-订阅】模式
MSF的名字是 Message Service Framework 的简称,由于目前框架主要功能在于处理即时(immediately)消息,所以iMSF就是 immediately Message S ...
- “一切都是消息”--iMSF(即时消息服务框架)之【请求-响应】模式(点对点)
MSF的名字是 Message Service Framework 的简称,由于目前框架主要功能在于处理即时(immediately)消息,所以iMSF就是 immediately Message S ...
- “一切都是消息”--MSF(消息服务框架)入门简介
“一切都是消息”--这是MSF(消息服务框架)的设计哲学. MSF的名字是 Message Service Framework 的简称,中文名称:消息服务框架,它是PDF.NET框架的一部分. 1,M ...
- “一切都是消息”--MSF(消息服务框架)之【发布-订阅】模式
在上一篇,“一切都是消息”--MSF(消息服务框架)之[请求-响应]模式 ,我们演示了MSF实现简单的请求-响应模式的示例,今天来看看如何实现[发布-订阅]模式.简单来说,该模式的工作过程是: 客户端 ...
- “一切都是消息”--MSF(消息服务框架)之【请求-响应】模式
在前一篇, “一切都是消息”--MSF(消息服务框架)入门简介, 我们介绍了MSF基于异步通信,支持请求-响应通信模式和发布-订阅通信模式,并且介绍了如何获取MSF.今天,我们来看看如何使用MSF来做 ...
- .net平台 基于 XMPP协议的即时消息服务端简单实现
.net平台 基于 XMPP协议的即时消息服务端简单实现 昨天抽空学习了一下XMPP,在网上找了好久,中文的资料太少了所以做这个简单的例子,今天才完成.公司也正在准备开发基于XMPP协议的即时通讯工具 ...
随机推荐
- Android 上传文件到 FTP 服务器
实现背景 近期接触到一个需求,就是将文件从Android系统上传到FTP服务器,虽然之前接触过FTP服务器,了解基本的使用流程,但是将此流程从使用习惯转化为代码实现还是有一定难度的.但是基本的流程还是 ...
- Java 虚拟机的对象创建
堆中存储的内容:在程序运行时,动态创建的对象. 创建对象的四种方式:new,clone(浅复制),反射,反序列化. 浅复制:只能复制当前对象本身,如果当前对象(A)引用了另外的对象(B),则引用对象( ...
- 在虚拟机上安装redis集群,redis使用版本为4.0.5,本机通过命令客户端可以连接访问,外部主机一直访问不了
在虚拟机上安装了redis 4 ,启动后本机客户端可以连接访问,但是外部主机一直访问不了,在使用java代码连接redis集群时报:no reachable node in cluster,原因:在r ...
- python实现线性排序算法-计数排序
计数排序假定输入元素的每一个都是介于0到k之间的整数,此处K为某个整数,当k=O(n)时,计数排序的运行时间为O(n) 它的基本思想是:根据每个输入元素x确定小于x的元素个数,根据这个信息把x直接放到 ...
- python网络编程初级
网络编程的专利权应该属于Unix,各个平台(如windows.Linux等).各门语言(C.C++.Python.Java等)所实现的符合自身特性的语法都大同小异.在我看来,懂得了Unix的socke ...
- 用eclipse导入打war包的maven项目
最近遇到Maven管理下的Spring MVC项目,组内某位将项目代码扔过来,一脸懵逼(囧),查阅了一些资料后终于将此项目运行通了(>_<),特此记录下来与各位分享. 通俗的来说,Mave ...
- 如何在Mac下配置Github和Bitbucket的SSH
--- title: 如何在Mac下配置Github和Bitbucket的SSH date: 2017-12-23 21:10:30 tags: - Mac - Git - Github catego ...
- 修改centos 7 系统时间
查看当前系统时间 date 修改当前系统时间 date -s "2018-2-22 19:10:30 查看硬件时间 hwclock --show 修改硬件时间 hwclock --set - ...
- 高可用Hadoop平台-应用JAR部署
1.概述 今天在观察集群时,发现NN节点的负载过高,虽然对NN节点的资源进行了调整,同时对NN节点上的应用程序进行重新打包调整,负载问题暂时得到缓解.但是,我想了想,这样也不是长久之计.通过这个问题, ...
- 【PyTorch深度学习60分钟快速入门 】Part3:神经网络
神经网络可以通过使用torch.nn包来构建. 既然你已经了解了autograd,而nn依赖于autograd来定义模型并对其求微分.一个nn.Module包含多个网络层,以及一个返回输出的方法f ...