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运用的最多,因为他放弃的是强一致性,追求的是最终一致性,性价比最高
    image

2.3 分布式事务应用场景

2.3.1 典型支付场景

这是最经典的场景。支付过程,要先对买家账户进行扣款,同时对卖家账户进行付款,
像这类的操作,
必须在一个事务中执行,保证原子性,要么都成功,要么都不成功。
但是往往买家的支付平台和卖家的支付平台不一致,即使都在一个平台下,所属的业务服务和数据服务
(归属不同表甚至不同库,比如卖家中心库、卖家中心库)也不是同一个。针对于不同的业务平台、不同的数据库做操作必然要引入分布式事务。

2.3.2 在线下单场景

同理,买家在电商平台下单,往往会涉及到两个动作,
一个是扣库存,第二个是更新订单状态
,库存和订单一般属于不同的数据库,需要使用分布式事务保证数据一致性。
image

2.3.3 跨行转账场景

跨行转账问题也是一个典型的分布式事务,用户A同学向B同学的账户转账500,要先进行A同学的账户-500,然后B同学的账户+500,既然是
不同的银行,涉及不同的业务平台,为了保证这两个操作步骤的一致,分布式事务必然要被引入。
image

3 分布式事务解决方案

常见的分布式一致性保障有如下方案

3.1 XA 两阶段提交协议

两阶段提交协议(Two-phase commit protocol,简称2PC)是一种分布式事务处理协议,旨在确保参与分布式事务的所有节点都能达成一致的结果。此协议被广泛应用于许多分布式关系型数据管理系统,以完成分布式事务。
它是一种强一致性设计,引入一个事务协调者的角色来协调管理各参与者的提交和回滚,二阶段分别指的是准备(投票)和提交两个阶段。
1、准备阶段(Prepare phase)
在此阶段,
协调者询问所有参与者是否可以提交事务。如果参与者的事务操作实际执行成功,则返回一个“同意”消息;如果执行失败,则返回一个“终止”消息。
下面是两个参与者都执行成功的结果:
image

准备阶段只要有一个参与者返回失败,那么协调者就会向所有参与者发送回滚事务的请求,即分布式事务执行失败。如下图:
image

2、提交阶段(Commit phase)
协调者根据所有参与者的应答结果判定是否事务可以全局提交(Commit 请求),并通知所有参与者执行该决定。
如果所有参与者都同意提交,则协调者让所有参与者都提交事务,向事务协调者返回“完成”消息。整个分布式事务完成。
如果其中某个参与者终止提交,则协调者让所有参与者都回滚事务。

image

如果其中一个Commit 不成功,那其他的应该也是提交不成功的。
image

3.2 XA三阶段提交

三阶段提交:
CanCommit 阶段、PreCommit 阶段、DoCommit 阶段,简称3PC
三阶段提交协议(Three-phase commit protocol,3PC),是二阶段提交(2PC)的改进版本。与两阶段提交不同的是,三阶段提交有两个改动点:在协调者和参与者中都引入超时机制,同时引入了预提交阶段。

在第一阶段和第二阶段中插入的预提交阶段,保证了在最后提交阶段之前各参与节点的状态是一致的。
即 3PC 把 2PC 的准备阶段再次一分为二,这样三阶段提交就有 CanCommit、PreCommit、DoCommit 三个阶段。
当 CanCommit、PreCommit、DoCommit的任意一个步骤失败或者等待超时,执行RollBack。

image

通过引入PreCommit阶段,3PC在一定程度上解决了2PC中协调者单点故障的问题,因为即使协调者在PreCommit阶段后发生故障,参与者也可以根据自身的状态来决定是否提交事务。然而,3PC并不是完美的解决方案,它仍然有一些缺点,比如增加了协议的复杂性和可能的性能开销。因此,在选择是否使用3PC时,需要根据具体的业务场景和需求进行权衡。

3.3 MQ事务

利用消息中间件来异步完成事务的后半部分更新,实现系统的最终一致性。
这个方式避免了像XA协议那样的性能问题。
下面的图中,使用MQ完成事务在分布式的另外一个子系统上的操作,保证了动作一致性。所以整个消息的生产和消息的消费动作需要全部完成,才算一个事务结束

image

3.4 TCC事务

TCC事务是Try、Confirm、Cancel三种指令的缩写
,其逻辑模式类似于XA两阶段提交,但是实现方式是在代码层面人为实现。
2PC 和 3PC 都是数据库层面的,而 TCC 是业务层面的分布式事务。
这种事务模式特别适用于需要强一致性保证的分布式事务场景,除了上面提到的数据库层面的操作外,例如电商平台的订单系统、跨行转账、分布式资源预订系统以及金融交易处理等。
下图就是一个典型的分布式系统的原子性操作,涉及A、B、C三个服务的执行。
如果有一个服务 try 出问题,整个事务管理器就执行calcel,如果三个try都成功,才执行confirm做正式提交。

image

如图,TCC事务分为三个阶段执行:

  1. Try阶段:主要是对业务系统做检测及资源预留。(执行2、3步骤)
  2. Confirm阶段:确认执行业务操作。如果Try阶段成功,则执行Confirm操作,提交事务。(执行4、5步骤)
  3. Cancel阶段:取消执行业务操作。如果Try阶段失败或超时,则执行Cancel操作,回滚事务。(执行4、5步骤)

3.5 最终补偿机制,同于MQ事务

最后使用补偿机制做最后的一致性保障,MQ方案尽量使用补偿机制进行保障。
如下图,对于发送成功,消费失败的消息,进入
Dead-Letter Queu
,使用单独的作业服务进行独立处理,比如重新发送死信消息进行消费,避免生产和消费的不一致,保证了最终的原子性、一致性。
image

4 总结

本文介绍了分布式系统的基础知识,以及分布式业务场景下保障分布式事务数据一致性、Action原子性的解决方案。
后续章节我们对分布式算法和常用框架进行介绍。

标签: none

添加新评论