分布式事务

时间:2024-06-17 19:12:27编辑:花茶君

如何提高分布式事务性能

这两年来,随着NoSQL系统、CAP理论和Eventual Consistency的大热,关于分布式操作要保证强一致还是弱一致性的讨论络驿不绝。双方各执一词,倾向实现强一致性的一方认为弱一致性满足不了应用开发的需要,倾向实现弱一致性的一方则认为保证强一致性将导致系统性能与可伸缩性难以接受。弱一致性能否满足应用开发的需求这一点由应用特征决定,难以一概而论,但强一致性对系统性能、可伸缩性和可用性的影响则是可以作技术分析的。奇怪的是,找了很久,也没找到对这一问题的深入分析,决定自己来做一个。

对于分布式操作,一般来说有以下两种实现选择:
1、 在每个节点上使用单独的事务,只实现弱一致性。
2、 使用2PC保证强一致性。即分布式事务协调者先要求所有参与节点PREPARE,大家都说PREPARE成功后,再要求所有节点COMMIT。只要有一个节点PREPARE不成功,大家都要回滚。这样参与者要强制写两次日志,协调者在决定要COMMIT时也要强制写一次日志。

首先,假设用户发起分布式操作的速率为TpS(Transactions per Second),每个分布式操作平均会操作K个节点。在每个节点上,平均要操作RpT(Rows per Transaction)条记录,而操作每条记录平均要用时TpR(Time per Row),这样在每个节点上事务操作的执行时间为:
TExec=RpT×TpR
另外,设定以下参数:
- N:数据库中所有节点上的总记录数
- TCommit:在每个节点上PREPARE或COMMIT的时间,PREPARE和COMMIT的主要工作都是写相应的日志,执行时间接近

对分布式操作性能方面一种常见的认识是若使用2PC,将导致事务执行时间大为延长,从而导致过高的事务并发冲突和死锁。当然,从趋势上使用2PC自然会导致并发冲突和死锁增长,但是否能满足应用需求,需要定量的来分析。由于死锁的概率完全取决于冲突概率,以下只分析冲突概率。

对选择1,即每个节点用独立事务时,用户发起的每个事务都会被分成K个小事务,这时系统中的并发事务数是事务速率与事务持续时间之积,即:
CT_1=TpS×K×(RpT×TpR+TCommit)
当某事务要锁定并操作某条记录时,系统中被其它事务所锁定的记录数是(CT_1-1)×RpT≈CT_1×RpT。假设事务操作的记录是纯随机的,则该事务要锁定的记录与其它事务冲突的概率是(CT_1×RpT)/N。而这个事务总共要锁定RpT条记录,则该事务与其它事务冲突的概率是:
TWait_1=1-(1-(CT_1×RpT)/N )^RpT≈CT_1×RpT^2/N

对选择2,即使用2PC保证强一致性时,每个节点上需要强制写两次日志,在事务协调者上还要强制写一次PREPARE日志(事务协调者上的COMMIT日志不需要强制写,这一时间可以忽略)。系统中的并发事务数是:
CT_2=TpS×((RpT×TpR+2×TCommit)×K+TCommit)
但此时系统中被其它事务所锁定的记录数是选择1的K倍,且事务要锁定的记录数也是选择1的K倍,这时事务的冲突概率是:
TWait_2≈CT_2×RpT^2×K^2/N
这个公式比较复杂,我们先简化一下,假设TCommit和TPrepare时间相对于TExec来说可以忽略,则可以得到有:
TWait_2=TWait_1×K^2
也就是说事务冲突的概率将会随着分布式操作涉及的节点数K的平方数增长。平方数增长听起来比较厉害,但实际上在真实应用中K通常是很小的,绝大多数情况下等于2。如经典的转账问题,就只涉及两个节点,还有比如建立好友关系时也只涉及两个节点。在使用我们分布式数据库的大量应用中(总共包含约500张表,上千个索引,几千种SQL模式),绝大多数情况下K为2,很少有3,超过3的更是绝无仅有。因此,如果我们忽略2PC PREPARE和提交的时间,则使用2PC时会导致事务冲突概率4~9倍的增长。

换一种情况,如果执行很快但提交写日志很慢,即TExec相对于TCommit来说可以忽略,则可以得到:
TWait_2=TWait_1×(2×K+1)/K×K^2
这时的情况比只考虑执行时间时差一些,但还是随着分布式操作涉及的节点数K的平方数增长,只不过从4~9倍变成10~21倍。

真实的情况一般在这两者之间,作为估算,可以大致认为采用2PC保证强一致性时将导致事务冲突概率增加8倍左右。

性能方面还涉及到吞吐率和响应时间。类似的进行分析,可以发现如果TCommit相对于TExec可以忽略,则响应时间不受2PC影响,反之,则2PC会导致响应时间增加为原来的3倍,平均的估计可以取增加1倍。对大多数应用,日志提交的吞吐率完全足够,则事务吞吐率不受2PC影响,反之,事务吞吐率会下降一半。

对大多数WEB应用冲突概率非常低,分布式操作只涉及2~3个节点,日志提交的吞吐率完全足够,则使用2PC可能带来的影响是事务冲突与死锁增加8倍左右,响应时间延长1倍,吞吐率不受影响。这些性能影响应该说是完全可以接受的,此时2PC带来的强一致性优点可以说远远超过其对性能的影响。

当然,以上分析中忽略了很多因素,比如网络延时,比如客户端在发起事务的多个操作之间还可能休息一会。加入这些因素后的性能分析会更复杂,但这些因素,本质上是使事务的持续时间增加,跟是否使用2PC无关。使用2PC与不使用2PC之间的性能差异比例,与这些因素关系不大。

但有一个问题需要注意。如果让客户端直接充当分布式事务的协调者,由于客户端上通常不像数据库服务器那样配置带电池的写缓存,fsync的性能很差,2PC将导致简单分布式事务的响应时间增加一个数量级,冲突概率更是可能增加两个数量级,事务提交的吞吐率也可能受到影响。解决方法是部署专职的高性能分布式事务协调者集群,配置高性能的日志存储设备如SSD。

基于这一基本的性能分析,还有一些变种:
1、如果分布式操作在各节点上并行执行,可以计算出冲突概率将是不并行的1/K。这仍比不用2PC串行高K倍,但不再是K的平方倍。比如BigTable中对二级索引和主记录的修改,就可以并行。
2、如果分布式操作是否冲突只取决于其中一个节点,可以计算出2PC并不会导致冲突概率显著增加。符合这一特征的应用模式还是BigTable中对主记录及其所有二级索引的修改,冲不冲突,完全取决于是否更新同一条记录,跟索引无关。
根据这两点也可以看出,如果用并行的2PC来保证主记录及其二级索引之间的一致性,其所带来的性能影响弱于2PC对一般分布式事务的影响,是完全可以实用的方案。

对使用2PC分布式事务的另外一个比较大的担心是如果2PC在PREPARE之后事务协调者崩溃,则参与分布式事务的各个节点只能长时间的锁定资源,等待协调者复活后告诉它事务应该提交还是回滚。如果直接让客户端直接充当分布式事务的协调者,这一问题可能很严重,因为客户端多而杂,崩溃概率高。但如果部署了专职的高性能分布式事务协调者集群,则这一问题基本可以避免。


分布式事务

1、两阶段提交协议

分为两个阶段:一个准备阶段 ,一个提交阶段。基于两阶段协议,事务管理器能够最大限度地保证跨数据库操作的事务原子性,是分布式系统环境下最严格的事务实现方法。但是两阶段协议存在性能方面问题,难于进行水平伸缩,因为在提交事务过程中,事务管理器需要每个参与者进行准备和提交的操作协调,在准备阶段锁定资源,在提交阶段消费资源。由于参与者众多,锁定资源和消费资源之间的时间差被拉长,导致响应速度较慢,产生死锁或不确定结果的可能性较大。在互联网很少使用两阶段提交协议。

两阶段提交协议是阻塞协议,在极端情况下不能快速响应请求方,因此提出了三阶段提交协议,解决了两阶段提交协议的阻塞问题,但仍然需要事务管理器在参与者之间协调,才能完成一个分布式事务。

2、最大努力保证模式

这是一种非常通用的保证分布式一致性的模式,很多开发人员一直在使用,但是未认识到这是一种模式,最大努力保证模式适用于对一致性要求并不十分严格但是对性能要求较高的场景。

具体的实现方式是:在更新多个资源时,将多个资源的提交尽量延后到最后一刻处理,如果业务流程出现问题,则所有的资源更新都可以回滚,事务仍然保持一致。唯一可能出现问题的是在提交多个资源时发生了系统问题,比如网络问题等。但是这种情况是非常罕见的,一旦出现这种情况,就需要进行实时补偿,将已提交的事务进行回滚。 当然在使用这种模式时,我们要考虑每个资源的提交顺序。我们在生产实践中遇到的一种反模式,就是在数据库事务中嵌套远程调用,而且远程调用的是耗时任务,导致数据库事务被拉长,最后拖垮数据库。

3、事务补偿机制

在对性能要求很高的场景中,两阶段提交协议不是一种好方案,最大努力保证模式也会使多个分布式操作相互嵌套,有可能相互影响。这里我们给出事务补偿机制,其性能很高,并且能尽最大可能地保证事务的一致性。

在数据库分库分表后,如果涉及的多个更新操作在某一个数据库范围内完成,则可以使用数据库内的本地事务保证一致性。对于跨库的多个操作,可通过补偿和重试,使其在一定的时间窗口内完成操作,这样就可以实现事务的最终一致性,突破事务遇到问题就回滚的传统思路。 如果采用事务补偿机制,则在遇到问题时,需要记录遇到问题的环境、信息、步骤、状态等,后续通过重试机制使其达到最终一致性。


嵌套事务和分布式的区别

嵌套事务和分布式事务是两个概念,它们之间有以下区别:1. 事务层次不同:嵌套事务是在同一事务中包含多个子事务,而分布式事务是不同主机上的多个事务进行协调。2. 控制粒度不同:嵌套事务通常是在单个数据库中实现,控制粒度较小;而分布式事务则更为复杂,需要协调跨越多个计算机和数据库的事务。3. 数据库锁定粒度不同:在嵌套事务中,锁定粒度相对较小,只需要锁定子事务所操作的数据;而在分布式事务中,需要对多个数据库中的数据进行锁定。4. 可用性不同:嵌套事务相对简单,因此可用性更高;而分布式事务由于需要跨越不同计算机和数据库,因此可用性相对较低,并且需要更多的复杂性来确保事务的可靠性。5. 同步机制不同:嵌套事务同步机制相对简单,通常采用语言编写的控制结构实现;而分布式事务则需要借助更先进的同步机制,如两阶段提交协议等。综上所述,嵌套事务和分布式事务是两个不同的概念,它们分别用于解决不同场景下的事务处理问题。


SQLServer2000分布式事务错误解决方法

SQLServer2000分布式事务错误解决方法
如果在Windows.NETServer上安装的SQLServer2000中运行链接服务器查询,可能会返回下列错误(即使MSDTC正在该服务器上运行):
症状如果在Windows.NETServer上安装的SQLServer2000中运行链接服务器查询,可能会返回下列错误(即使MSDTC正在该服务器上运行):Server:Msg8501,Level16,State3,Line3
MSDTConserver'servername'isunavailable.在SQLServer错误日志中,您会发现由运行该查询的spid引发的下列错误:ResourceManagerCreationFailed:ResultCode=0x8004d01c原因这是设计使然。如果在"本地系统"帐户下运行"分布式事务处理协调器服务"就会发生此错误。解决方案最近为了提高RPC安全性对DTC所做的更改要求MSDTC作为"NTAuthority\NetworkService"运行。这是。NETServer的默认选项。在WindowsNT和Windows2000中,默认情况下MSDTC服务是在"本地系统"帐户下运行的。
警告:"注册表编辑器"使用不当可造成严重问题,这些问题可能需要重新安装操作系统。Microsoft不保证能够解决因为"注册表编辑器"使用不当而产生的问题。使用"注册表编辑器"需要您自担风险。
若要将MSDTC服务帐户从"本地系统"更改为"NTAuthority\NetworkService",请执行下列步骤:1.运行regedt32,浏览至HKEY_LOCAL_MACHINE\Software\Microsoft\MSDTC.添加一个DWORD值TurnOffRpcSecurity,值数据为1.2.打开命令提示,运行"netstopmsdtc",然后运行"netstartmsdtc".3.转至"组件服务管理工具".
a.浏览至"启动管理工具".
b.选择"组件服务".
c.展开"组件服务"树,然后展开"我的电脑".
d.右键单击"我的电脑",然后选择"属性".
e.在MSDTC选项卡中,确保选中了下列选项:网络DTC访问网络管理网络事务XA事务另外,"DTC登录帐户"一定要设置为"NTAuthority\NetworkService".
f.单击"确定".这样将会提示您"MSDTC将会停止并重新启动。所有的依赖服务将被停止。请按'是'继续".单击"是"继续。
g.单击"确定"关闭"我的电脑"属性窗口。
4.再次运行regedt32,浏览至HKEY_LOCAL_MACHINE\Software\Microsoft\MSDTC,然后删除TurnOffRpcSecurity项。现在您的MSDTC服务应该在"NTAuthority\NetworkService"帐户下运行了,并且不会再出现该错误。
更多信息当"MSDTC安全性"配置下的"网络DTC访问"禁用时,如果运行链接服务器查询则会返回下列错误:Server:Msg7391,Level16,State1,Line2TheoperationcouldnotbeperformedbecausetheOLEDBprovider'SQLOLEDB'
wasunabletobeginadistributedtransaction.[OLE/DBproviderreturnedmessage:Newtransactioncannotenlistinthespecifiedtransactioncoordinator.]
跟踪标记7300打开时:Server:Msg7391,Level16,State1,Line2TheoperationcouldnotbeperformedbecausetheOLEDBprovider'SQLOLEDB'
wasunabletobeginadistributedtransaction.[OLE/DBproviderreturnedmessage:Newtransactioncannotenlistinthespecifiedtransactioncoordinator.]OLEDBerrortrace[OLE/DBProvider'SQLOLEDB'ITransactionJoin::JoinTransactionreturned0x8004d00a].
MSDTC服务一定要按照上面"解决方案"一节中的说明进行设置,才能防止此错误。
再现现象的步骤
1.转至"启动管理工具服务".
2.右键单击"分布式事务处理协调器"服务,转至"登录"选项卡,选择"登录身份"下的"本地系统"帐户。
3.停止然后重新启动该服务。
4.从查询分析器,运行下列脚本:execsp_addlinkedserverremote1execsp_setnetnameremote1,goexecremote1.pubs.dbo.sp_executesqlN'createtablet(c1int)'gosetxact_abortongobegintraninsertintoremote1.pubs.dbo.tvalues(1)committrango


谈谈分布式事务有哪些特点

现今互联网界,分布式系统和微服务架构盛行。一个简单操作,在服务端非常可能是由多个服务和数据库实例协同完成的。在一致性要求较高的场景下,多个独立操作之间的一致性问题显得格外棘手。基于水平扩容能力和成本考虑,传统的强一致的解决方案(e.g.单机事务)纷纷被抛弃。其理论依据就是响当当的CAP原理。往往为了可用性和分区容错性,忍痛放弃强一致支持,转而追求最终一致性。分布式系统的特性在分布式系统中,同时满足CAP定律中的一致性 Consistency、可用性 Availability和分区容错性 Partition Tolerance三者是不可能的。在绝大多数的场景,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证最终一致性。https://www.zhihu.com/question/65292792/answer/229459320


求救,分布式事务怎么处理

1.性能和时延问题在服务化之前,业务通常都是本地API调用,本地方法调用性能损耗较小。服务化之后,服务提供者和消费者之间采用远程网络通信,增加了额外的性能损耗:1)客户端需要对消息进行序列化,主要占用CPU计算资源。2)序列化时需要创建二进制数组,耗费JVM堆内存或者堆外内存。3)客户端需要将序列化之后的二进制数组发送给服务端,占用网络带宽资源。4)服务端读取到码流之后,需要将请求数据报反序列化成请求对象,占用CPU计算资源。5)服务端通过反射的方式调用服务提供者实现类,反射本身对性能影响就比较大。6)服务端将响应结果序列化,占用CPU计算资源。7)服务端将应答码流发送给客户端,占用网络带宽资源。8)客户端读取应答码流,反序列化成响应消息,占用CPU资源。通过分析我们发现,一个简单的本地方法调用,切换成远程服务调用之后,额外增加了很多处理流程,不仅占用大量的系统资源,同时增加了时延。一些复杂的应用会拆分成多个服务,形成服务调用链,如果服务化框架的性能比较差、服务调用时延也比较大,业务服务化之后的性能和时延将无法满足业务的性能需求。1.1 RPC框架高性能设计影响RPC框架性能的主要因素有三个。1)I/O调度模型:同步阻塞I/O(BIO)还是非阻塞I/O(NIO)。2)序列化框架的选择:文本协议、二进制协议或压缩二进制协议。3)线程调度模型:串行调度还是并行调度,锁竞争还是无锁化算法。1.I/O调度模型在I/O编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者I/O多路复用技术进行处理。I/O多路复用技术通过把多个I/O的阻塞复用到同一个select的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求。与传统的多线程/多进程模型比,I/O多路复用的最大优势是系统开销小,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程的运行,降低了系统的维护工作量,节省了系统资源。JDK1.5_update10版本使用epoll替代了传统的select/poll,极大地提升了NIO通信的性能,它的工作原理如图1-1所示。图1-1 非阻塞I/O工作原理Netty是一个开源的高性能NIO通信框架:它的I/O线程NioEventLoop由于聚合了多路复用器Selector,可以同时并发处理成百上千个客户端Channel。由于读写操作都是非阻塞的,这就可以充分提升I/O线程的运行效率,避免由于频繁I/O阻塞导致的线程挂起。另外,由于Netty采用了异步通信模式,一个I/O线程可以并发处理N个客户端连接和读写操作,这从根本上解决了传统同步阻塞I/O一连接一线程模型,架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。Netty被精心设计,提供了很多独特的性能提升特性,使它做到了在各种NIO框架中性能排名第一,它的性能优化措施总结如下。1)零拷贝:(1)Netty的接收和发送ByteBuffer采用DIRECTBUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝。如果使用传统的堆内存(HEAPBUFFERS)进行Socket读写,JVM会将堆内存Buffer拷贝一份到直接内存中,然后才写入Socket中。相比于堆外直接内存,消息在发送过程中多了一次缓冲区的内存拷贝。(2)Netty提供了组合Buffer对象,可以聚合多个ByteBuffer对象,用户可以像操作一个Buffer那样方便地对组合Buffer进行操作,避免了传统通过内存拷贝的方式将几个小Buffer合并成一个大的Buffer。(3)Netty的文件传输采用了transferTo方法,它可以直接将文件缓冲区的数据发送到目标Channel,避免了传统通过循环write方式导致的内存拷贝问题。2)内存池:随着JVM虚拟机和JIT即时编译技术的发展,对象的分配和回收是个非常轻量级的工作。但是对于缓冲区Buffer,情况却稍有不同,特别是对于堆外直接内存的分配和回收,是一件耗时的操作。为了尽量重用缓冲区,Netty提供了基于内存池的缓冲区重用机制。性能测试表明,采用内存池的ByteBuf相比于朝生夕灭的ByteBuf,性能高23倍左右(性能数据与使用场景强相关)。3)无锁化的串行设计:在大多数场景下,并行多线程处理可以提升系统的并发性能。但是,如果对于共享资源的并发访问处理不当,会带来严重的锁竞争,这最终会导致性能的下降。为了尽可能地避免锁竞争带来的性能损耗,可以通过串行化设计,即消息的处理尽可能在同一个线程内完成,期间不进行线程切换,这样就避免了多线程竞争和同步锁。为了尽可能提升性能,Netty采用了串行无锁化设计,在I/O线程内部进行串行操作,避免多线程竞争导致的性能下降。表面上看,串行化设计似乎CPU利用率不高,并发程度不够。但是,通过调整NIO线程池的线程参数,可以同时启动多个串行化的线程并行运行,这种局部无锁化的串行线程设计相比一个队列-多个工作线程模型性能更优。4)高效的并发编程:volatile的大量、正确使用;CAS和原子类的广泛使用;线程安全容器的使用;通过读写锁提升并发性能。2.高性能序列化框架影响序列化性能的关键因素总结如下。1)序列化后的码流大小(网络带宽的占用)。2)序列化&反序列化的性能(CPU资源占用)。3)是否支持跨语言(异构系统的对接和开发语言切换)。4)并发调用的性能表现:稳定性、线性增长、偶现的时延毛刺等。相比于JSON等文本协议,二进制序列化框架性能更优异,以Java原生序列化和Protobuf二进制序列化为例进行性能测试对比,结果如图1-2所示。图1-2 序列化性能测试对比数据在序列化框架的技术选型中,如无特殊要求,尽量选择性能更优的二进制序列化框架,码流是否压缩,则需要根据通信内容做灵活选择,对于图片、音频、有大量重复内容的文本文件(例如小说)可以采用码流压缩,常用的压缩算法包括GZip、Zig-Zag等。3.高性能的Reactor线程模型该模型的特点总结如下。1)有专门一个NIO线程:Acceptor线程用于监听服务端,接收客户端的TCP连接请求。2)网络I/O操作:读、写等由一个NIO线程池负责,线程池可以采用标准的JDK线程池实现,它包含一个任务队列和N个可用的线程,由这些NIO线程负责消息的读取、解码、编码和发送。3)1个NIO线程可以同时处理N条链路,但是1个链路只对应1个NIO线程,防止产生并发操作。由于Reactor模式使用的是异步非阻塞I/O,所有的I/O操作都不会导致阻塞,理论上一个线程可以独立处理所有I/O相关的操作,因此在绝大多数场景下,Reactor多线程模型都可以完全满足业务性能需求。Reactor线程调度模型的工作原理示意如图1-3所示。图1-3 高性能的Reactor线程调度模型1.2 业务最佳实践要保证高性能,单依靠分布式服务框架是不够的,还需要应用的配合,应用服务化高性能实践总结如下:1)能异步的尽可能使用异步或者并行服务调用,提升服务的吞吐量,有效降低服务调用时延。2)无论是NIO通信框架的线程池还是后端业务线程池,线程参数的配置必须合理。如果采用JDK默认的线程池,最大线程数建议不超过20个。因为JDK的线程池默认采用N个线程争用1个同步阻塞队列方式,当线程数过大时,会导致激烈的锁竞争,此时性能不仅不会提升,反而会下降。3)尽量减小要传输的码流大小,提升性能。本地调用时,由于在同一块堆内存中访问,参数大小对性能没有任何影响。跨进程通信时,往往传递的是个复杂对象,如果明确对方只使用其中的某几个字段或者某个对象引用,则不要把整个复杂对象都传递过去。举例,对象A持有8个基本类型的字段,2个复杂对象B和C。如果明确服务提供者只需要用到A聚合的C对象,则请求参数应该是C,而不是整个对象A。4)设置合适的客户端超时时间,防止业务高峰期因为服务端响应慢导致业务线程等应答时被阻塞,进而引起后续其他服务的消息在队列中排队,造成故障扩散。5)对于重要的服务,可以单独部署到独立的服务线程池中,与其他非核心服务做隔离,保障核心服务的高效运行。6)利用Docker等轻量级OS容器部署服务,对服务做物理资源层隔离,避免虚拟化之后导致的超过20%的性能损耗。7)设置合理的服务调度优先级,并根据线上性能监控数据做实时调整。2.事务一致性问题服务化之前,业务采用本地事务,多个本地SQL调用可以用一个大的事务块封装起来,如果某一个数据库操作发生异常,就可以将之前的SQL操作进行回滚,只有所有SQL操作全部成功,才最终提交,这就保证了事务强一致性,如图2-1所示。服务化之后,三个数据库操作可能被拆分到独立的三个数据库访问服务中,此时原来的本地SQL调用演变成了远程服务调用,事务一致性无法得到保证,如图2-2所示。图2-2 服务化之后引入分布式事务问题假如服务A和服务B调用成功,则A和B的SQL将会被提交,最后执行服务C,它的SQL操作失败,对于应用1消费者而言,服务A和服务B的相关SQL操作已经提交,服务C发生了回滚,这就导致事务不一致。从图2-2可以得知,服务化之后事务不一致主要是由服务分布式部署导致的,因此也被称为分布式事务问题。2.1 分布式事务设计方案通常,分布式事务基于两阶段提交实现,它的工作原理示意图如图2-3所示。图2-3 两阶段提交原理图阶段1:全局事务管理器向所有事务参与者发送准备请求;事务参与者向全局事务管理器回复自己是否准备就绪。阶段2:全局事务管理器接收到所有事务参与者的回复之后做判断,如果所有事务参与者都可以提交,则向所有事务提交者发送提交申请,否则进行回滚。事务参与者根据全局事务管理器的指令进行提交或者回滚操作。分布式事务回滚原理图如图2-4所示。图2-4 分布式事务回滚原理图两阶段提交采用的是悲观锁策略,由于各个事务参与者需要等待响应最慢的参与者,因此性能比较差。第一个问题是协议本身的成本:整个协议过程是需要加锁的,比如锁住数据库的某条记录,且需要持久化大量事务状态相关的操作日志。更为麻烦的是,两阶段锁在出现故障时表现出来的脆弱性,比如两阶段锁的致命缺陷:当协调者出现故障,整个事务需要等到协调者恢复后才能继续执行,如果协调者出现类似磁盘故障等错误,该事务将被永久遗弃。对于分布式服务框架而言,从功能特性上需要支持分布式事务。在实际业务使用过程中,如果能够通过最终一致性解决问题,则不需要做强一致性;如果能够避免分布式事务,则尽量在业务层避免使用分布式事务。2.2 分布式事务优化既然分布式事务有诸多缺点,那么为什么我们还在使用呢?有没有更好的解决方案来改进或者替换呢?如果我们只是针对分布式事务去优化的话,发现其实能改进的空间很小,毕竟瓶颈在分布式事务模型本身。那我们回到问题的根源:为什么我们需要分布式事务?因为我们需要各个资源数据保持一致性,但是对于分布式事务提供的强一致性,所有业务场景真的都需要吗?大多数业务场景都能容忍短暂的不一致,不同的业务对不一致的容忍时间不同。像银行转账业务,中间有几分钟的不一致时间,用户通常都是可以理解和容忍的。在大多数的业务场景中,我们可以使用最终一致性替代传统的强一致性,尽量避免使用分布式事务。在实践中常用的最终一致性方案就是使用带有事务功能的MQ做中间人角色,它的工作原理如下:在做本地事务之前,先向MQ发送一个prepare消息,然后执行本地事务,本地事务提交成功的话,向MQ发送一个commit消息,否则发送一个rollback消息,取消之前的消息。MQ只会在收到commit确认才会将消息投递出去,所以这样的形式可以保证在一切正常的情况下,本地事务和MQ可以达到一致性。但是分布式调用存在很多异常场景,诸如网络超时、VM宕机等。假如系统执行了local_tx()成功之后,还没来得及将commit消息发送给MQ,或者说发送出去由于网络超时等原因,MQ没有收到commit,发生了commit消息丢失,那么MQ就不会把prepare消息投递出去。MQ会根据策略去尝试询问(回调)发消息的系统(checkCommit)进行检查该消息是否应该投递出去或者丢弃,得到系统的确认之后,MQ会做投递还是丢弃,这样就完全保证了MQ和发消息的系统的一致性,从而保证了接收消息系统的一致性。3.研发团队协作问题服务化之后,特别是采用微服务架构以后。研发团队会被拆分成多个服务化小组,例如AWS的TwoPizzaTeam,每个团队由2~3名研发负责服务的开发、测试、部署上线、运维和运营等。随着服务数的膨胀,研发团队的增多,跨团队的协同配合将会成为一个制约研发效率提升的因素。3.1 共用服务注册中心为了方便开发测试,经常会在线下共用一个所有服务共享的服务注册中心,这时,一个正在开发中的服务发布到服务注册中心,可能会导致一些消费者不可用。解决方案:可以让服务提供者开发方,只订阅服务(开发的服务可能依赖其他服务),而不注册正在开发的服务,通过直连测试正在开发的服务。它的工作原理如图3-1所示。图3-1 只订阅,不发布3.2 直连提供者在开发和测试环境下,如果公共的服务注册中心没有搭建,消费者将无法获取服务提供者的地址列表,只能做本地单元测试或使用模拟桩测试。还有一种场景就是在实际测试中,服务提供者往往多实例部署,如果服务提供者存在Bug,就需要做远程断点调试,这会带来两个问题:1)服务提供者多实例部署,远程调试地址无法确定,调试效率低下。2)多个消费者可能共用一套测试联调环境,断点调试过程中可能被其他消费者意外打断。解决策略:绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直联方式将以服务接口为单位,忽略注册中心的提供者列表。3.3 多团队进度协同假如前端Web门户依赖后台A、B、C和D4个服务,分别由4个不同的研发团队负责,门户要求新特性2周内上线。A和B内部需求优先级排序将门户的优先级排的比较高,可以满足交付时间点。但是C和D服务所在团队由于同时需要开发其他优先级更高的服务,因此把优先级排的相对较低,无法满足2周交付。在C和D提供版本之前,门户只能先通过打测试桩的方式完成Mock测试,但是由于并没有真实的测试过C和D服务,因此需求无法按期交付。应用依赖的服务越多,特性交付效率就越低下,交付的速度取决于依赖的最迟交付的那个服务。假如Web门户依赖后台的100个服务,只要1个核心服务没有按期交付,则整个进度就会延迟。解决方案:调用链可以将应用、服务和中间件之间的依赖关系串接并展示出来,基于调用链首入口的交付日期作为输入,利用依赖管理工具,可以自动计算出调用链上各个服务的最迟交付时间点。通过调用链分析和标准化的依赖计算工具,可以避免人为需求排序失误导致的需求延期。3.4 服务降级和Mock测试在实际项目开发中,由于小组之间、个人开发者之间开发节奏不一致,经常会出现消费者等待依赖的服务提供者提供联调版本的情况,相互等待会降低项目的研发进度。解决方案:服务提供者首先将接口定下来并提供给消费者,消费者可以将服务降级同Mock测试结合起来,在Mock测试代码中实现容错降级的业务逻辑(业务放通),这样既完成了Mock测试,又实现了服务降级的业务逻辑开发,一举两得。3.5 协同调试问题在实际项目开发过程中,各研发团队进度不一致很正常。如果消费者坐等服务提供者按时提供版本,往往会造成人力资源浪费,影响项目进度。解决方案:分布式服务框架提供Mock桩管理框架,当周边服务提供者尚未完成开发时,将路由切换到模拟测试模式,自动调用Mock桩;业务集成测试和上线时,则要能够自动切换到真实的服务提供者上,可以结合服务降级功能实现。3.6 接口前向兼容性由于线上的Bug修复、内部重构和需求变更,服务提供者会经常修改内部实现,包括但不限于:接口参数变化、参数字段变化、业务逻辑变化和数据表结构变化。在实际项目中经常会发生服务提供者修改了接口或者数据结构,但是并没有及时知会到所有消费者,导致服务调用失败。解决方案:1)制定并严格执行《服务前向兼容性规范》,避免发生不兼容修改或者私自修改不通知周边的情况。2)接口兼容性技术保障:例如Thrift的IDL,支持新增、修改和删除字段,字段定义位置无关性,码流支持乱序等。4.总结服务化之后,无论是服务化框架,还是业务服务,都面临诸多挑战,本章摘取了其中一些比较重要的问题,并给出解决方案和最佳实践。对于本章节没有列出的问题,则需要服务框架开发者和使用者在实践中探索,找出一条适合自己产品的服务化最佳实践。


什么叫分布式事务,在SQL Server中如何配置

MSDTC(Microsoft Distributed Transaction Coordinator)中文叫微软分布式事务处理协调器,负责WINDOWS平台的分布式事务处理。SQL SERVER的事务如果需要和本数据库之外(包括别的数据库)的事务协同完成同一个事务,那么就需要MSTDC来掌控,否则SQL SERVER的事务就是普通的本地数据库事务,和MSDTC没有关系,数据库自身就能处理了。




很多组织机构慢慢的在不同的服务器和地点部署SQL Server数据库——为各种应用和目的——开始考虑通过SQL Server集群的方式来合并。

将SQL Server实例和数据库合并到一个中心的地点可以减低成本,尤其是维护和软硬件许可证。此外,在合并之后,可以减低所需机器的数量,这些机器就可以用于备用。

当寻找一个备用,比如高可用性的环境,企业常常决定部署Microsoft的集群架构。我常常被问到小的集群(由较少的节点组成)SQL Server实例和作为中心解决方案的大的集群哪一种更好。在我们比较了这两个集群架构之后,我让你们自己做决定。

什么是Microsoft集群服务器

MSCS是一个Windows Server企业版中的内建功能。这个软件支持两个或者更多服务器节点连接起来形成一个“集群”,来获得更高的可用性和对数据和应用更简便的管理。MSCS可以自动的检查到服务器或者应用的失效,并从中恢复。你也可以使用它来(手动)移动服务器之间的负载来平衡利用率以及无需停机时间来调度计划中的维护任务。

这种集群设计使用软件“心跳”来检测应用或者服务器的失效。在服务器失效的事件中,它会自动将资源(比如磁盘和IP地址)的所有权从失效的服务器转移到活动的服务器。注意还有方法可以保持心跳连接的更高的可用性,比如站点全面失效的情况下。

MSCS不要求在客户计算机上安装任何特殊软件,因此用户在灾难恢复的经历依赖于客户-服务器应用中客户一方的本质。客户的重新连接常常是透明的,因为MSCS在相同的IP地址上重启应用、文件共享等等。进一步,为了灾难恢复,集群的节点可以处于分离的、遥远的地点。

在集群服务器上的SQL Server

SQL Server 2000可以配置为最多4个节点的集群,而SQL Server 2005可以配置为最多8个节点的集群。当一个SQL Server实例被配置为集群之后,它的磁盘资源、IP地址和服务就形成了集群组来实现灾难恢复。

SQL Server 2000允许在一个集群上安装16个实例。根据在线帮助,“SQL Server 2005在一个服务器或者处理器上可以支持最多50个SQL Server实例,”但是,“只能使用25个硬盘驱动器符,因此如果你需要更多的实例,那么需要预先规划。”

注意SQL Server实例的灾难恢复阶段是指SQL Server服务开始所需要的时间,这可能从几秒钟到几分钟。如果你需要更高的可用性,考虑使用其他的方法,比如log shipping和数据库镜像。

单个的大的SQL Server集群还是小的集群

下面是大的、由更多的节点组成的集群的优点:

◆更高的可用新(更多的节点来灾难恢复)。

◆更多的负载均衡选择(更多的节点)。

◆更低廉的维护成本。

◆增长的敏捷性。多达4个或者8个节点,依赖于SQL版本。

◆增强的管理性和简化环境(需要管理的少了)。

◆更少的停机时间(灾难恢复更多的选择)。

◆灾难恢复性能不受集群中的节点数目影响。

下面是单个大的集群的缺点:

◆集群节点数目有限(如果需要第9个节点怎么办)。

◆在集群中SQL实例数目有限。

◆没有对失效的防护——如果磁盘阵列失效了,就不会发生灾难恢复。

◆使用灾难恢复集群,无法在数据库级别或者数据库对象级别,比如表,创建灾难恢复集群。

虚拟化和集群

虚拟机也可以参与到集群中,虚拟和物理机器可以集群在一起,不会发生问题。SQL Server实例可以在虚拟机上,但是性能可能会受用影响,这依赖于实例所消耗的资源。在虚拟机上安装SQL Server实例之前,你需要进行压力测试来验证它是否可以承受必要的负载。

在这种灵活的架构中,如果虚拟机和物理机器集群在一起,你可以在虚拟机和物理机器之间对SQL Server进行负载均衡。比如,使用虚拟机上的SQL Server实例开发应用。然后在你需要对开发实例进行压力测试的时候,将它灾难恢复到集群中更强的物理机器上。

集群服务器可以用于SQL Server的高可用性、灾难恢复、可扩展性和负载均衡。单个更大的、由更多的节点组成的集群往往比小的、只有少数节点的集群更好。大个集群允许更灵活环境,为了负载均衡和维护,实例可以从一个节点移动到另外的节点。


使用@Transactional和不加@Transactional 有什么区别

额,你发错分类了。。。
transactional是JAVA的Spring框架的注解,倡导的是低入侵性,能够更良好的使用AOP面向切面编程。
transactionlal加上了,代表这个类会被Spring操作或者声明,具体的操作根据transactional的内容而定。
不加上当然Spring就不会自动识别了,需要IOC反向控制一下。
transactional范围还是很广的,具体你需要查阅更多的资料才能学会它


想用Zookeeper实现分布式事务,不知道可行不可行

前期准备

1.修改Linux主机名,每台都得配置
vim /etc/sysconfig/network

NETWORKING=yes
HOSTNAME=hadoop-server1

2.修改IP /etc/sysconfig/network-scripts/ifcfg-eth0

3.修改主机名和IP的映射关系
vim /etc/hosts

192.168.146.181 hadoop-server1
192.168.146.182 hadoop-server2
192.168.146.183 hadoop-server3
192.168.146.184 hadoop-server4
192.168.146.185 hadoop-server5
######注意######如果你们公司是租用的服务器或是使用的云主机(如华为用主机、阿里云主机等)
/etc/hosts里面要配置的是内网IP地址和主机名的映射关系

4.关闭防火墙
#查看防火墙状态
service iptables status
#关闭防火墙
service iptables stop
#查看防火墙开机启动状态
chkconfig iptables --list
#关闭防火墙开机启动
chkconfig iptables off

前4步用root用户操作,操作完后重启机器
5.ssh免登陆hadoop用户操作
#生成ssh免登陆密钥
#进入到我的home目录
cd ~/.ssh

ssh-keygen -t rsa (四个回车)
执行完这个命令后,会生成两个文件id_rsa(私钥)、id_rsa.pub(公钥)
将公钥拷贝到要免密登陆的目标机器上
ssh-copy-id hadoop-server2

6.安装JDK,配置环境变量等root用户操作
vim /etc/proflie
export JAVA_HOME=/usr/java/jdk1.7.0_65
export HADOOP_HOME=/itcast/hadoop-2.4.1
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

source /etc/profile

集群规划:
主机名 IP 安装软件 运行进程
hadoop-server1 192.168.146.181:jdk、hadoop
namenode resourcemanage
DFSZKFailoverController(zkfc)
hadoop-server2 192.168.146.182:jdk、hadoop
namenode resourcemanage
DFSZKFailoverController(zkfc)
hadoop-server3 192.168.146.183:jdk、hadoop、zookeeper
datanode nodemanage
journalnode QuorumPeerMain
hadoop-server4 192.168.146.184:jdk、hadoop、zookeeper
datanode nodemanage
journalnode QuorumPeerMain
hadoop-server5 192.168.146.185:jdk、hadoop、zookeeper
datanode nodemanage
journalnode QuorumPeerMain

安装步骤:
1.安装配置zooekeeper集群(在hadoop-server3上)
1.1解压
tar -zxvf zookeeper-3.4.5.tar.gz -C /home/hadoop/app/
1.2修改配置
cd /home/hadoop/app/zookeeper-3.4.5/conf/
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
修改:dataDir=/home/hadoop/app/zookeeper-3.4.5/data
在最后添加:
server.1=hadoop-server3:2888:3888
server.2=hadoop-server4:2888:3888
server.3=hadoop-server5:2888:3888
保存退出
然后创建一个tmp文件夹
mkdir /home/hadoop/app/zookeeper-3.4.5/data
再创建一个空文件
touch /home/hadoop/app/zookeeper-3.4.5/data/myid
最后向该文件写入ID
echo 1 > /home/hadoop/app/zookeeper-3.4.5/data/myid
1.3将配置好的zookeeper拷贝到其他节点
scp -r /home/hadoop/app/zookeeper-3.4.5/ weekend06:/home/hadoop/app/
scp -r /home/hadoop/app/zookeeper-3.4.5/ weekend07:/home/hadoop/app/

注意:修改hadoop-server4、hadoop-server5对应/home/hadoop/app/zookeeper-3.4.5/data/myid内容
hadoop-server4:
echo 2 > /home/hadoop/app/zookeeper-3.4.5/data/myid
hadoop-server5:
echo 3 > /home/hadoop/app/zookeeper-3.4.5/data/myid

2.安装配置hadoop集群(在hadoop-server1上操作)
2.1解压
tar -zxvf hadoop-2.4.1.tar.gz -C /weekend/
2.2配置HDFS(hadoop2.0所有的配置文件都在$HADOOP_HOME/etc/hadoop目录下)
#将hadoop添加到环境变量中
vim /etc/profile
export JAVA_HOME=/hadoop/home/app/jdk1.7.0_55
export HADOOP_HOME=/home/hadoop/app/hadoop-2.4.1
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin

#hadoop2.0的配置文件全部在$HADOOP_HOME/etc/hadoop下
cd /home/hadoop/app/hadoop-2.4.1/etc/hadoop

2.2.1修改hadoo-env.sh
export JAVA_HOME=/home/hadoop/app/jdk1.7.0_55

2.2.2修改core-site.xml



fs.defaultFS
hdfs://ns1/



hadoop.tmp.dir
/home/hadoop/app/hadoop-2.4.1/tmp




ha.zookeeper.quorum
hadoop-server3:2181,hadoop-server3:2181,hadoop-server3:2181



2.2.3修改hdfs-site.xml



dfs.nameservices
ns1



dfs.ha.namenodes.ns1
nn1,nn2



dfs.namenode.rpc-address.ns1.nn1
hadoop-server1:9000



dfs.namenode.http-address.ns1.nn1
hadoop-server1:50070



dfs.namenode.rpc-address.ns1.nn2
weekend02:9000



dfs.namenode.http-address.ns1.nn2
hadoop-server2:50070



dfs.namenode.shared.edits.dir
qjournal://hadoop-server3:8485;hadoop-server4:8485;hadoop-server5:8485/ns1



dfs.journalnode.edits.dir
/home/hadoop/app/hadoop-2.4.1/journaldata



dfs.ha.automatic-failover.enabled
true



dfs.client.failover.proxy.provider.ns1
org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider



dfs.ha.fencing.methods

sshfence
shell(/bin/true)




dfs.ha.fencing.ssh.private-key-files
/home/hadoop/.ssh/id_rsa



dfs.ha.fencing.ssh.connect-timeout
30000



2.2.4修改mapred-site.xml



mapreduce.framework.name
yarn



2.2.5修改yarn-site.xml



yarn.resourcemanager.ha.enabled
true



yarn.resourcemanager.cluster-id
yrc



yarn.resourcemanager.ha.rm-ids
rm1,rm2



yarn.resourcemanager.hostname.rm1
hadoop-server1


yarn.resourcemanager.hostname.rm2
hadoop-server2



yarn.resourcemanager.zk-address
hadoop-server3:2181,hadoop-server4:2181,hadoop-server5:2181


yarn.nodemanager.aux-services
mapreduce_shuffle



2.2.6修改slaves(slaves是指定子节点的位置)
hadoop-server3
hadoop-server4
hadoop-server5


上一篇:桃江武潭

下一篇:自体脂肪注射除皱