分布式系统基础概括

分布式系统是什么

分布式系统:一个硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统

这是分布式系统,在不同的硬件,不同的软件,不同的网络,不同的计算机上,仅仅通过消息来进行通讯与协调,这是他的特点,更细致的看这些特点又可以有:分布性、对等性、并发性、缺乏全局时钟、故障随时会发生

分布性

既然是分布式系统,最显著的特点肯定就是分布性,从简单来看,如果我们做的是个电商项目,整个项目会分成不同的功能,专业点就不同的微服务,比如用户微服务,产品微服务,订单微服务,这些服务部署在不同的 tomcat 中,不同的服务器中,甚至不同的集群中,整个架构都是分布在不同的地方的,在空间上是随意的,而且随时会增加,删除服务器节点这是第一个特性

对等性

对等性是分布式设计的一个目标,还是以电商网站为例,来说明下什么是对等性,要完成一个分布式的系统架构,肯定不是简单的把一个大的单一系统拆分成一个个微服务,然后部署在不同的服务器集群就够了,其中拆分完成的每一个微服务都有可能发现问题,而导致整个电商网站出现功能的丢失

比如订单服务,为了防止订单服务出现问题,一般情况需要有一个备份,在订单服务出现问题的时候能顶替原来的订单服务,这就要求这2个(或者2个以上)订单服务完全是对等的,功能完全是一致的,还有比如数据库,缓存等,都和上面说的订单服务一样,为了安全考虑需要有完全一样的备份存在,这就是对等性的意思

并发性

从多进程,多JVM的角度,例如:在一个分布式系统中的多个节点,可能会并发地操作一些共享资源,如何准确并高效的协调分布式并发操作,分布式锁就是为了解决这个问题

缺乏全局时钟

在分布式系统中,节点是可能反正任意位置的,而每个位置,每个节点都有自己的时间系统(例如英国和中国的时区不同),因此在分布式系统中,很难定义两个事务纠结谁先谁后,原因就是因为缺乏一个全局的时钟序列进行控制,所以需要一个时间服务器给系统调用

故障随时会发生

任何一个节点都可能出现停电,死机等现象,服务器集群越多,出现故障的可能性就越大,随着集群数目的增加,出现故障甚至都会成为一种常态

分布式系统协调 “方法论”

分布式系统带来的问题

如果把分布式系统和平时的交通系统进行对比,哪怕再稳健的交通系统也会有交通事故,分布式系统也有很多需要攻克的问题,比如:通讯异常,网络分区,三态,节点故障等

通信异常

通讯异常其实就是网络异常,网络系统本身是不可靠的,由于分布式系统需要通过网络进行数据传输,网络光纤,路由器等硬件难免出现问题

网络分区(脑裂现象)

网络分区,其实就是脑裂现象,说的简单点就是把比如你的顶头上司A生病了,生病之前给你安排了后面几天的工作,这时候,公司怕你们不知道干啥,又给你们安排了一个上司B,这时候上司B又叫你干别的工作,这时候就出现了两个负责人在给你安排工作,共享你的工作安排资源,这就是脑裂现象

在分布式集群中就是2个(或者2个以上)的节点之间相互通信,假如主节点挂了,那么从节点就要顶替主节点的工作,接收主节点的资源,但是这个时候因为某些原因,从节点都连不上主节点了,那么接收主节点资源负责主节点工作,但是这个时候主节点其实还没有挂,只是从节点通信不上了,所以就造成了脑裂现象,2个节点都在共享公共资源

三态

三态即是除了成功态,失败态之外的第三种状态,称为超时态

在分布式系统中,虽然绝大多数情况下能够接受到成功或者失败的相应,但一旦网络出现异常,就非常有可能出现超时,当出现这样的超时现象,网络通讯的发起方,是无法确定请求是否成功处理的

节点故障

节点故障在分布式系统下是比较常见的问题,指的是组成服务器集群的节点会出现的宕机或节点异常下线的现象,所以通常有主从节点

CAP理论

前面说了分布式可能产生的很多的问题,那么有什么理论思想来解决呢?接下来就说说 CAP 和 BASE 理论

CAP 其实就是一致性可用性分区容错性这三个词的缩写

一致性

一致性是事务 ACID 的一个特性[原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)]

这里讲的一致性其实大同小异,在分布式系统中,一致性是数据在多个副本之间是否能够保证一致的特性,这里说的一致性和前面说的对等性其实差不多。如果能够在分布式系统中针对某一个数据项的变更成功执行后,所有用户都可以马上读取到最新的值,那么这样的系统就被认为具有 强一致性,当然通常情况下我们根据业务可以允许 延时一致性最终一致性

可用性

可用性指系统提供服务必须 一直处于可用状态,对于用户的操作请求总是能够在 有限的时间内 访问结果

这里的重点是 有限的时间返回结果

  • 为了做到有限的时间需要用到缓存,需要用到负载,这个时候服务器增加的节点是为性能考虑
  • 为了返回结果,需要考虑服务器主备,当主节点出现问题的时候需要备份的节点能最快的顶替上来,千万不能出现 OutOfMemory 或者其他 500,404 错误,否则这样的系统我们会认为是不可用的

分区容错性

分布式系统在遇到任何网络分区故障的时候,仍然需要能够对外提供满足一致性和可用性的服务,除非是整个网络环境都发生了故障

不能出现脑裂的情况

具体描述

一个分布式系统不可能同时满足一致性、可用性和分区容错性这三个基本需求,最多只能同时满足其中的两项

  1. 放弃P(满足CA):将数据和服务都放在一个节点上,避免因网络引起的负面影响,充分保证系统的可用性和一致性。但放弃P意味着放弃了系统的可扩展性
  2. 放弃A(满足CP):当节点故障或者网络故障时,受到影响的服务需要等待一定的时间,因此在等待时间里,系统无法对外提供正常服务,因此是不可用的
  3. 放弃C(满足AP):系统无法保证数据的实时一致性,但是承诺数据最终会保证一致性。因此存在数据不一致的窗口期,至于窗口期的长短取决于系统的设计

因为不可能把P放弃,把所有应用全部放到一个节点上,所以往往需要根据业务场景再A和C之间寻求平衡

BASE理论

根据前面的 CAP 理论,应该从一致性和可用性之间找平衡,系统短时间完全不可用肯定是不允许的,那么根据 CAP 理论,在分布式环境下必然也无法做到强一致性

BASE 理论:即使无法做到强一致性,但分布式系统可以根据自己的业务特点,采用适当的方式来使系统达到最终的一致性

Basically Avaliable 基本可用

当分布式系统出现不可预见的故障时,允许损失部分可用性,保障系统的“基本可用”;体现在“时间上的损失”和“功能上的损失”

例如:部分用户双十一高峰期淘宝页面卡顿或降级处理

Soft state 软状态

其实就是前面讲到的三态,既允许系统中的数据存在中间状态,既系统的不同节点的数据副本之间的数据同步过程存在延时,并认为这种延时不会影响系统可用性

例如:12306买火车票的候补席位,其实请求就是进入了排队队列

Eventually consistent 最终一致性

所有的数据在经过一段时间的数据同步后,最终能够达到一个一致的状态

例如:银行之间的转账,余额短暂时间内数据不一致

分布式系统的协调一致性算法

前面提到了 CAP理论 和 BASE理论,这些都是理论,那么有什么算法可以具体来协调一致性呢?那么就有了下面的 2PC,3PC,Paxos算法

2PC(两阶段提交)

过程描述

2PC中,每个事务需要一个协调者来协调各个参与者,每个事务分为两步执行

  • 第一阶段:准备阶段
    • 协调者向所有参与者发送事务内容,询问是否可以执行事务操作
    • 各参与者执行事务,写事务日志但不进行提交,各参与者锁定事务相关的资源,保证事务可以正常提交
    • 各参与者向协调者返回响应,YES表示可以提交,NO表示不可以提交。若协调者收到所有参与者的YES回复,则准备进行事务提交,若有参与者回复NO或者超时,则准备回滚事务
  • 第二阶段:提交事务阶段
    • 协调者向所有参与者发送提交请求,参与者正式提交事务,并在完成后释放相关资源

2PC的优点

原理简单,实现方便

2PC的缺点

同步阻塞,单点问题,数据不一致,容错性不好

  • 同步阻塞:在一阶段等待调教的过程中,所有的节点都在等待其他节点的响应,无法进行其他操作,这种同步阻塞极大的限制了分布式系统的性能
  • 单点问题:协调者在整个二阶段提交过程中很重要,如果协调者在提交阶段出现问题,那么整个流程将无法运转。更重要的是,其他参与者将会处于一直锁定事务资源的状态中,而无法继续完成事务操作
  • 数据不一致:假设当协调者向所有的参与者发送 commit 请求之后,发生了局部网络异常,或者是协调者在尚未发送完所有 commit 请求之前自身发生了崩溃,导致最终只有部分参与者收到了commit 请求,这将导致严重的数据不一致问题
  • 容错性不好:二阶段提交协议没有设计较为完善的容错机制,任意一个节点是失败都会导致整个事务的失败

3PC(三阶段提交)

3PC中,同样需要协调者和参与者,但是它又细分了准备阶段,在一定程度上减少了同步阻塞和单点问题,但是前面提到的数据一致性问题反而更严重了

过程描述

  • 第一阶段:canCommit
    • 协调者向所有参与者发送 CanCommit 请求
    • 各参与者判断是否可以完成事务提交,但不执行事务也不锁定资源
    • 各参与者根据是否可以完成事务向协调者回复 YES 或 NO
  • 第二阶段:PreCommit
    • 协调者向所有参与者发送 PreCommit 请求,执行事务操作
    • 各参与者执行事务,写事务日志但不进行提交,各参与者锁定事务相关的资源,保证事务可以正常提交
    • 各参与者向协调者返回响应,若协调者收到所有参与者的 YES 回复,则准备进行事务提交,若有参与者回复NO或者超时,则回滚事务
  • 第三阶段:doCommit
    • 协调者向所有参与者发送提交请求,参与者正式提交事务,如果协调者故障了,参与者一直没有收到指令,那么参与者会在超时之后自动提交事务,之后释放资源

虽然2PC和3PC都存在问题,但是基本上所有的分布式事务都是借助二阶段或者三阶段的思想来扩散成其他的算法

Paxos

Paxos算法的实现是有难度的,本身这算法的提出者莱斯利·兰伯特在前面几篇论文中都不是以严谨的数学公式进行的

前面提到了2PC,3PC,它们要求收到所有参与者的 ACK 消息后才认为提交成功,而 Paxos 只要 超过半数 的参与者响应了那么即认为是成功的,即少数服从多数

其实这个 paxos 算法也分成两阶段,首先这个图有 2 个角色,提议者与接收者

比如用一个简单的例子来说明:

  • 第一阶段
    • 提议者对接收者吼了一嗓子,我有个事情要告诉你们,当然这里接受者不只一个,它也是个分布式集群
    • 相当于星期一开早会,可耻的领导吼了句:“要开会了啊,我要公布一个编号为 001 的提案,收到请回复”。
    • 这个时候领导就会等着,等员工回复 1 “好的”,如果回复的数目超过一半,就会进行下一步
    • 如果由于某些原因(接收者死机,网络问题,本身业务问题),导通过的协议未超过一半,这个时候的领导又会再吼一嗓子,当然气势没那凶残:“好了,怕了你们了,我要公布一个新的编号未 002 的提案,收到请回复 1
    • 如果这个阶段一直没有超过半数,那么就会一直循环下去
  • 第二阶段
    • 接下来到第二阶段,领导苦口婆心的把你们叫来开会了,今天编号 002 提案的内容是:“由于项目紧张,今天加班到 12 点,同意的请举手”这个时候如果绝大多少的接收者都同意,那么好,议案就这么决定了
    • 如果员工反对或者直接夺门而去,那么领导又只能从第一个阶段开始:“大哥,大姐们,我有个新的提案 003,快回会议室吧。”

大概就这么理解了