1分布式系统介绍
1.1 分布式系统的发展
我们早期的集中式系统都是单体架构的,整个系统作为一个单体粒度的应用存在,所有的模块聚合在一起。明显的弊端就是不易扩展、发布冗重、服务稳定性治理不好做。
随着微服务架构的不断大规模应用,驱使我们把整个系统拆分成若干个具备独立运行能力的计算服务的集合,
通过交互协作,完成庞大、复杂的业务流程,用户感知单一,但实际上,它是一个分布式服务的集合。
分布式系统主要从以下几个方面进行裂变:
1、应用可以从业务领域拆分成多个module,单个module再按项目结构分成接口层、业务层、数据访问层;也可以按照用户领域区分,如对移动、桌面、Web端访问的入口流量拆分不同类型接口服务。参考我的这篇《微服务架构拆分策略》,
2、数据存储层可以按业务类型拆分成多个数据库实例,还可以对单库或单表进行更细粒度的分库分表;参考我的这篇《MySQL分库分表》
3、通过一些业务中间件的支撑来保证分布式系统的可用性,如分布式缓存、搜索服务、NoSQL数据库、文件服务、消息队列等中间件。
1.2 存在的优势和不足
分布式系统可以解决集中式不便扩展的弊端,提供了便捷的扩展性、独立的服务治理,并提高了安全可靠性。随着微服务技术(Spring Cloud、Dubbo) 以及容器技术(Kubernetes、Docker)的大热,分布式技术发展非常迅速。
不足的地方:分布式系统虽好,也给系统带来了复杂性,如分布式事务、分布式锁、分布式session、数据一致性等都是现在分布式系统中需要解决的难题,虽然已经有很多成熟的方案,但都不完美。
分布式系统的便利,其实是牺牲了一些开发、测试、发布、运维、资源 成本的,让工作量增加了,所以分布式系统管理不好反而会变成一种负担。
2 分布式事务及应用场景
2.1 使用分布式事务解决问题
我们上面说了,分布式系统给业务带来了一些复杂性,所以,衍生出分布式事务来应对和解决这些问题。
分布式事务是指允许多个独立的事务资源参与到一个全局的事务中,其参与者、支持事务的服务器、资源服务器以及事务管理器分别位于分布式系统的不同节点之上。这些节点属于同一个Action行为,如果有一个节点的结果不同步,就会造成整体的数据不一致。分布式事务需要保证这些action要么全部成功,要么全部失败,从而保证单个完整操作的原子性,也保证了各节点数据的一致性。
2.2 CAP定理
CAP 定理(也称为 Brewer 定理),指的是在分布式计算环境下,有3个核心的需求:
1、一致性(Consistency):再分布,所有实例节点同一时间看到是相同的数据
2、可用性(Availability):不管是否成功,确保每一个请求都能接收到响应
3、分区容错性(Partition Tolerance):系统任意分区后,在网络故障时,仍能操作
CAP理论告诉我们,分布式系统不可能同时满足以下三种。最多只能同时满足其中的两项,大多数分布式业务中P是必须的, 因此往往选择就在CP或者AP。
- CA: 放弃分区容错性。非分布式架构,比如关系数据库,因为没有分区,但是在分布式系统下,CA组合就不建议了。
- AP: 放弃强一致性。追求最终一致性,类似的场景比如转账,可以接受两小时后到账,Eureka的注册也是类似的做法。
- CP: 放弃可用性。zookeeper在leader宕机后,选举期间是不提供服务的。类似的场景比如支付完成之后出订单,必须一进一出都完成才行。
说明:在分布式系统中AP运用的最多,因为他放弃的是强一致性,追求的是最终一致性,性价比最高
2.3 分布式事务应用场景
2.3.1 典型支付场景
这是最经典的场景。支付过程,要先对买家账户进行扣款,同时对卖家账户进行付款,
像这类的操作,必须在一个事务中执行,保证原子性,要么都成功,要么都不成功。但是往往买家的支付平台和卖家的支付平台不一致,即使都在一个平台下,所属的业务服务和数据服务
(归属不同表甚至不同库,比如卖家中心库、卖家中心库)也不是同一个。针对于不同的业务平台、不同的数据库做操作必然要引入分布式事务。
2.3.2 在线下单场景
同理,买家在电商平台下单,往往会涉及到两个动作,一个是扣库存,第二个是更新订单状态,库存和订单一般属于不同的数据库,需要使用分布式事务保证数据一致性。
2.3.3 跨行转账场景
跨行转账问题也是一个典型的分布式事务,用户A同学向B同学的账户转账500,要先进行A同学的账户-500,然后B同学的账户+500,既然是不同的银行,涉及不同的业务平台,为了保证这两个操作步骤的一致,分布式事务必然要被引入。
3 分布式事务解决方案
常见的分布式一致性保障有如下方案
3.1 XA 两阶段提交协议
两阶段提交协议(Two-phase commit protocol,简称2PC)是一种分布式事务处理协议,旨在确保参与分布式事务的所有节点都能达成一致的结果。此协议被广泛应用于许多分布式关系型数据管理系统,以完成分布式事务。
它是一种强一致性设计,引入一个事务协调者的角色来协调管理各参与者的提交和回滚,二阶段分别指的是准备(投票)和提交两个阶段。
1、准备阶段(Prepare phase)
在此阶段,协调者询问所有参与者是否可以提交事务。如果参与者的事务操作实际执行成功,则返回一个"同意"消息;如果执行失败,则返回一个"终止"消息。
下面是两个参与者都执行成功的结果:
准备阶段只要有一个参与者返回失败,那么协调者就会向所有参与者发送回滚事务的请求,即分布式事务执行失败。如下图:
2、提交阶段(Commit phase)
协调者根据所有参与者的应答结果判定是否事务可以全局提交(Commit 请求),并通知所有参与者执行该决定。
如果所有参与者都同意提交,则协调者让所有参与者都提交事务,向事务协调者返回"完成"消息。整个分布式事务完成。
如果其中某个参与者终止提交,则协调者让所有参与者都回滚事务。
如果其中一个Commit 不成功,那其他的应该也是提交不成功的。
3.2 XA三阶段提交
三阶段提交:CanCommit 阶段、PreCommit 阶段、DoCommit 阶段,简称3PC
三阶段提交协议(Three-phase commit protocol,3PC),是二阶段提交(2PC)的改进版本。与两阶段提交不同的是,三阶段提交有两个改动点:在协调者和参与者中都引入超时机制,同时引入了预提交阶段。
在第一阶段和第二阶段中插入的预提交阶段,保证了在最后提交阶段之前各参与节点的状态是一致的。
即 3PC 把 2PC 的准备阶段再次一分为二,这样三阶段提交就有 CanCommit、PreCommit、DoCommit 三个阶段。当 CanCommit、PreCommit、DoCommit的任意一个步骤失败或者等待超时,执行RollBack。
通过引入PreCommit阶段,3PC在一定程度上解决了2PC中协调者单点故障的问题,因为即使协调者在PreCommit阶段后发生故障,参与者也可以根据自身的状态来决定是否提交事务。然而,3PC并不是完美的解决方案,它仍然有一些缺点,比如增加了协议的复杂性和可能的性能开销。因此,在选择是否使用3PC时,需要根据具体的业务场景和需求进行权衡。
3.3 MQ事务
利用消息中间件来异步完成事务的后半部分更新,实现系统的最终一致性。 这个方式避免了像XA协议那样的性能问题。
下面的图中,使用MQ完成事务在分布式的另外一个子系统上的操作,保证了动作一致性。所以整个消息的生产和消息的消费动作需要全部完成,才算一个事务结束
3.4 TCC事务
TCC事务是Try、Confirm、Cancel三种指令的缩写,其逻辑模式类似于XA两阶段提交,但是实现方式是在代码层面人为实现。 2PC 和 3PC 都是数据库层面的,而 TCC 是业务层面的分布式事务。
这种事务模式特别适用于需要强一致性保证的分布式事务场景,除了上面提到的数据库层面的操作外,例如电商平台的订单系统、跨行转账、分布式资源预订系统以及金融交易处理等。
下图就是一个典型的分布式系统的原子性操作,涉及A、B、C三个服务的执行。 如果有一个服务 try 出问题,整个事务管理器就执行calcel,如果三个try都成功,才执行confirm做正式提交。
如图,TCC事务分为三个阶段执行:
- Try阶段:主要是对业务系统做检测及资源预留。(执行2、3步骤)
- Confirm阶段:确认执行业务操作。如果Try阶段成功,则执行Confirm操作,提交事务。(执行4、5步骤)
- Cancel阶段:取消执行业务操作。如果Try阶段失败或超时,则执行Cancel操作,回滚事务。(执行4、5步骤)
3.5 最终补偿机制,同于MQ事务
最后使用补偿机制做最后的一致性保障,MQ方案尽量使用补偿机制进行保障。
如下图,对于发送成功,消费失败的消息,进入Dead-Letter Queu
,使用单独的作业服务进行独立处理,比如重新发送死信消息进行消费,避免生产和消费的不一致,保证了最终的原子性、一致性。
4 总结
本文介绍了分布式系统的基础知识,以及分布式业务场景下保障分布式事务数据一致性、Action原子性的解决方案。
后续章节我们对分布式算法和常用框架进行介绍。