每一个程序员架构梦的实现之路上,总是绕不开分布式系统CAP这个理论的学习。如果你还没有了解过,可以翻看之前的文章,相信我,如果你想成为架构师,这个理论无论是在工作中还是面试中吹水,你始终都是需要的
CAP理论作为分布式的重要理论基础,指出了在分布式环境下,其实只有AP和CP两种模型去选择。BASE理论作为CAP理论的一个延伸,主张牺牲一致性去换取可用性。反之,一个分布式系统也可以去牺牲可用性去换取一致性。
说到一致性就不能不提事务,事务这个词现在经常用于数据库,但是有一点要注意,站在一定的角度,事务并非只适用于数据库。如果站在数据库角度非要下一个定义的话:
事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
为了更好的认识并实现事务,抽象出了ACID理论,换句话说,如果一个系统能实现ACID特性,那么就实现了事务特性。
在单机上实现ACID并不困难,通常可以利用锁、时间序列或者顺序日志等机制来保证。这里多说一句,一般而言,隔离性可以利用锁机制来实现,而原子性、一致性和持久性都可以利用日志来实现,一致性算法Raft也是通过日志形式来保证一致性的。
但是在分布式环境下,网络环境却比单机要复杂的多,原因在于网络通信的不可靠性,处于不同网络的多个节点要想保证一致性,网络延迟、网络故障等因素都需要考虑。
二阶段(2PC)提交协议是根据业界首个分布式事务标准规范X/OpenDTP提出的,顾名思义,它通过两个阶段来协商一个提交操作。
X/OpenDTP设计了一个模型来描述分布式事务的各个角色以及规范:
二阶段提交协议最早用来实现数据库的分布式事务,现在大部分数据库的分布式事务都采用了XA协议。在二阶段提交协议中,一个事务的提交过程被分为两个过程:
二阶段协议的精髓在于,它通过两个阶段来把不可靠事务提交失败的几率降低到了最小,在一个真正的二阶段提交事务的过程中,第一阶段其实占据了整个事务的大部分时间,而真正提交事务的第二阶段几乎是瞬间完成的,所以这正是二阶段的巧妙之处。
但是现实中我们很少使用二阶段提交协议来保证事务性,为什么呢?
由于二阶段提交协议的一系列缺陷,TCC被引入分布式事务。TCC是Try(预留)、Confirm(确认)、Cancel(撤销)3个操作的简称,它包含了预留、确认或撤销这2个阶段。TCC针对分布式事务大体过程是这样的:
TCC本质上是补偿事务,从操作上就可以看出来,每个业务方针对当前事务需要注册三个操作:预留操作,确认操作,取消操作。这三个操作是需要参与事务的每个业务来编码实现的。对应到编码层面,每个业务方都需要提供三个操作的接口,为了一致性,确认操作和取消操作必须是幂等的,因为这两个操作可能会系统性的重试或者人为干预的重试。
TCC在操作上更像是一种编程模型,它主要针对业务层面,所以它在性能上要比主要针对数据库层面的二阶段提交要高很多。目前二阶段提交协议主要的应用场景还是在数据库上,所以它本质上使用的是数据库的锁机制,这也是在高并发的互联网应用中很少使用二阶段提交协议的重要原因之一。
说了那么多,在真实的业务场景中,如果能用单机数据库的事务来代替分布式事务,那就首选单机数据库事务。如果业务允许放弃强一致性,那就采用最终一致性原则来保证一致性,而最终一致性最常用的解决方案是利用可靠的MQ消息,这个有时间我们详聊。
领取专属 10元无门槛券
私享最新 技术干货