分布式事务初探
Posted 数据仓库与分析
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式事务初探相关的知识,希望对你有一定的参考价值。
说到数据库的事务,不得不说本地事务的四大特征ACID,即原子性,隔离性,一致性和持久性。那么什么是分布式事务呢?分布式事务的理论基础是什么?分布式事务如何实现?什么场景需要分布式事务?本文将要简单的介绍。
什么是分布式事务
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上,也就是不在一台机器,而是在分布在网络。
根据事务的特点,为了保证事务的原子性,一个事务由不同的小操作组成,而这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。
本质上来说,分布式事务就是为了保证不同数据库的数据一致性。
分布式事务产生的场景
随着互联网的发展,各种拥有大量用户的应用雨后春笋般的出现,分布式事务的场景现在随处可见。
简单的两个情况就是服务存在多个节点,资源存在多个节点。
对于资源来说,数据库就是一种资源,随着数据量的越来越大,我们可能需要进行分库分表,分库分表的出现,使得资源不在一个节点,假如一个转账业务,你给朋友转钱,有可能你的数据库是在北京,而你的朋友的钱是存在上海,那么分布式事务就是保证这个过程具有原子性。
分布式事务的理论基础
CAP理论
CAP理论的C就是一致性,A就是可用性,P就是分区容错性。
一致性:对客户端来说,读操作能返回最新的写操作。对于数据分布在不同节点上的数据上来说,如果在某个节点更新了数据,那么在其他节点如果都能读取到这个最新的数据,那么就称为强一致,如果有某个节点没有读取到,那就是分布式不一致。
可用性:非故障的节点在合理的时间内返回合理的响应。可用性的两个关键一个是合理的时间,一个是合理的响应。
分区容错性:当出现网络分区后,系统能够继续工作。
熟悉CAP的人都知道,三者不能共有,如果感兴趣可以搜索CAP的证明。
CA系统:在分布式系统中,网络无法百分之百可靠,分区其实是一个必然现象,所以一般没有CA架构,但是Kafka属于CA系统,得益于Kafka的分布式设计,kafka引入了Replication的概念,也就是有主节点和副节点,主节点复制数据到各个副节点从而增强了数据的持久性和可用性。Kafka的主节点和副本当然有可能网络不可用,针对主节点不可用有Leader选举机制,针对副本则维护一组可用活跃副本ISR的节点,副本不可达就从ISR剔除,网络可达再加入ISR,这样基本保障分区容错性。
CP系统:放弃可用性,追求一致性和分区容错性,常用的应用有Hbase、MongoDB、Redis,ZooKeeper等等。
AP系统:放弃一致性,追求分区容错性和可用性,这是很多分布式系统设计时的选择,后面的BASE也是根据AP来扩展。
BASE理论
BASE是Basically Available(基本可用)Soft state(软状态)和Eventually consistent(最终一致性)三个短语的缩写,是对CAP中AP的一个扩展。
基本可用:分布式系统在出现故障时,允许损失部分可用功能,保证核心功能可用。
软状态:允许系统中存在中间状态,这个状态不影响系统可用性,这里指的是CAP中的不一致。
最终一致:最终一致是指经过一段时间后,所有节点数据都将会达到一致。
BASE解决了CAP中理论没有网络延迟问题,在BASE中用软状态和最终一致性,保证了延迟后的一致性。
BASE和ACID是相反的,它完全不同于ACID的强一致性模型,是通过牺牲强一致性来获得可用性,并允许数据在一段时间内是不一致的,但最终达到一致状态。
分布式事务解决方案
2PC
也称为两阶段提交,第一阶段,事务管理器要求每个涉及到事务的数据库预提交此操作,并反映是否可以提交;也就是投票阶段。第二阶段,事务协调器要求每个数据库提交数据,或者回滚数据,也就是执行阶段。
两阶段提交的优点是尽量保证了数据的强一致,实现成本较低,在各大主流数据库都有自己实现。
两阶段提交的缺点也有很多,比如:
单点问题:事务管理器在整个流程中扮演的角色很关键,如果其宕机,比如在第一阶段已经完成,在第二阶段正准备提交的时候事务管理器宕机,资源管理器就会一直阻塞,导致数据库无法使用。
同步阻塞问题:在准备就绪之后,资源管理器中的资源一直处于阻塞,直到提交完成,释放资源。
数据不一致问题:两阶段提交协议虽然为分布式数据强一致性所设计,但仍然存在数据不一致性的可能,比如在第二阶段中,假设协调者发出了事务commit的通知,但是因为网络问题该通知仅被一部分参与者所收到并执行了commit操作,其余的参与者则因为没有收到通知一直处于阻塞状态,这时候就产生了数据的不一致性。
3PC
三段提交(3PC)是对两段提交(2PC)的一种升级优化,3PC在2PC的第一阶段中插入一个准备阶段。保证了在最后提交阶段之前,各参与者节点的状态都一致。同时在协调者和参与者中都引入超时机制,当参与者各种原因未收到协调者的commit请求后,会对本地事务进行commit,不会一直阻塞等待。
3PC 的三个阶段分别是CanCommit、PreCommit、DoCommit
CanCommit:协调者向所有参与者发送CanCommit命令,询问是否可以执行事务提交操作。如果全部响应YES则进入下一个阶段。
之前2PC的一阶段是本地事务执行结束后,最后不Commit,等其它服务都执行结束并返回Yes,由协调者发生commit才真正执行commit。
而这里的CanCommit指的是尝试获取数据库锁如果可以,就返回Yes。
PreCommit:协调者向所有参与者发送PreCommit命令,询问是否可以进行事务的预提交操作,参与者接收到PreCommit请求后,如参与者成功的执行了事务操作,则返回Yes响应,进入最终commit阶段。
一旦参与者中有向协调者发送了No响应,或因网络造成超时,协调者没有接到参与者的响应,协调者向所有参与者发送abort请求,参与者接受abort命令执行事务的中断。
在前一个阶段中,如果所有的参与者都返回Yes的话,那么就会进入PreCommit阶段进行事务预提交。这里的PreCommit阶段跟上面的第一阶段是差不多的,只不过这里协调者和参与者都引入了超时机制 (2PC中只有协调者可以超时,参与者没有超时机制)。
DoCommit:在前两个阶段中所有参与者的响应反馈均是YES后,协调者向参与者发送DoCommit命令正式提交事务,如协调者没有接收到参与者发送的ACK响应,会向所有参与者发送abort请求命令,执行事务的中断。
3PC对于协调者(Coordinator)和参与者(Partcipant)都设置了超时时间,而2PC只有协调者才拥有超时机制。这个优化点,主要是避免了参与者在长时间无法与协调者节点通讯(协调者挂掉了)的情况下,无法释放资源的问题,因为参与者自身拥有超时机制会在超时后,自动进行本地commit从而进行释放资源。而这种机制也侧面降低了整个事务的阻塞时间和范围。
另外,通过3PC三个阶段的设计,相较于2PC而言,多设置了一个缓冲阶段保证了在最后提交阶段之前各参与节点的状态是一致的。
3PC是为非阻塞而设计的,减少了2PC的阻塞问题。当参与者处于PRECOMMIT状态时,即使协调者故障导致参与者未收到后续的global-commit消息,参与者在超时后也能依据概率认为成功提交的概率很大,然后进行提交。
3PC还是没有解决2PC的一致性问题,并且还引入了新的一致性问题,假设由于网络原因,协调者发送的global-abort没有被某个参与者及时接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到参与者之间存在数据不一致的情况。
综上,3PC使用的不是很广泛。
TCC
TCC全称是Try-Confirm-Cancel,又被称补偿事务,TCC与2PC的思想很相似,事务处理流程也很相似,但2PC是应用于在DB层面,TCC则可以理解为在应用层面的2PC,是需要我们编写业务逻辑来实现。TCC它的核心思想是针对每个操作都要注册一个与其对应的确认Try和补偿Cancel。
Try阶段:尝试执行,完成所有业务检查(一致性),预留必须业务资源(准隔离性)
Confirm阶段:确认执行真正执行业务,不作任何业务检查,只使用Try阶段预留的业务资源,Confirm操作满足幂等性。要求具备幂等设计,Confirm失败后需要进行重试。
Cancel阶段:取消执行,释放Try阶段预留的业务资源,Cancel操作满足幂等性Cancel阶段的异常和Confirm阶段异常处理方案基本上一致。
TCC事务机制相比于上面介绍2PC,解决了其几个缺点:
解决了协调者单点,由主业务方发起并完成这个业务活动。业务活动管理器也变成多点,引入集群。
针对同步阻塞,引入超时,超时后进行补偿,并且不会锁定整个资源,将资源转换为业务逻辑形式,粒度变小。
针对数据一致性,有了补偿机制之后,由业务活动管理器控制一致性。
TCC的缺点也有很多,包括应用侵入性强开发难度大。TCC由于基于在业务层面,至使每个操作都需要有 try、confirm、cancel三个接口,这样代码开发量很大,要保证数据一致性 confirm 和 cancel 接口还必须实现幂等性。
以上是关于分布式事务初探的主要内容,如果未能解决你的问题,请参考以下文章