分布式的优劣势
我们在这里讨论的分布式系统主要是指同一模块内通过使用多节点实现的横向分布式,以此提升系统吞吐量,而不是基于任务集中性划分模块,并通过远程过程调用(RPC)实现整体串联的纵向分布式。
这种横向分布式架构的优点主要体现在以下两个方面:
- 数据备份:避免因单点故障导致数据丢失或服务无法使用;
- 负载均衡:多节点共享任务,理论上,单个节点的工作量会随着节点数量的增加而减少。
然而,由于网络的不确定性,横向分布式也带来了一些问题:
- 如何确保不同节点间数据的一致性?
- 最终一致性
- 立即一致性
- 如何确保分布式系统的稳定运行?避免出现所谓的脑裂、崩溃以及过长的延迟等问题
CAP理论
CAP是指Consistency(一致性),Availability(可用性)和Partition tolerance(分区容错性)。CAP理论是计算机科学中的一个著名猜想,它主张在分布式数据存储中,一致性、可用性和分区容错性,这三个核心属性无法同时达到最优。
让我们对每个属性进行详细的剖析:
- 一致性(Consistency) :一致性指的是在分布式系统中所有节点拥有相同的数据。当更新操作发生后,所有读取操作要么返回最新的写入、要么读取失败。这要求整个分布式系统像是一个不可拆分的整体,写操作作用于集群像作用于单机一样,具有广义的"原子性".
- 可用性(Availability) :可用性是指在分布式系统中,每次请求都能获取到(非错误)响应------不管该响应的状态如何,或者是否包含最新的数据。这要求系统既不发生错误,也不能出现过长的等待时间
- 分区容错性(Partition tolerance) :分区容错性意味着系统即使出现单个组件失败或网络问题,整个系统仍能正常运行。简单来说,系统应该能够容忍网络分区,不至于出现系统崩溃或者秩序混乱的局面.
CAP 理论强调的是,一个系统中,C、A、P 三项性质至多只能满足其二,即每个系统依据其架构设计会具有 CP、AP 或者 CA 的倾向性. 对于分布式系统而言, P 是必须得到保证的,否则这就违背了"分布式"的语义. 那么分布式系统会分为两种流派:
- CP:强调数据的正确性,牺牲了系统的可用性,比如在数据同步的时间段内系统不可用
- AP: 强调系统的可用性,牺牲了数据的一致性,比如在不同节点上读取到的数据不一致
C和A的矛盾主要在于网络的不确定性
一致性
顺序一致性
考虑如下一种场景:
- 客户端依次向 master 发送了 set x = 1、set x = 2 的两笔请求;
- master 在本机依次完成了两笔写操作,于是状态机中记录的结果为 x = 2;
- 同时,master 异步开启将请求同步到 follower 的任务,任务发出的顺序是先set x = 1 后 set x = 2;
- 由于网络问题,第 set x = 1 请求出了点状况,导致set x = 2请求后发先至
- 于是 follower 先执行set x = 2,后执行set x = 1,最终 follower 状态机内的结果为 x = 1.
follower记录了错误的数据,这个问题就很严重,接下来不论何时面对客户端的读请求都会返回这个错误的结果。
即时一致性
- 客户端写请求打到了 master,写入 x = 1 这一项内容;
- 紧接着,客户端读请求打到了 follower,查询 x 的值.这时答案是不确定的. 因为这取决于 master 和 follower 之间数据同步的机制.
倘若,为了满足更快响应客户端的诉求,服务端采用了异步完成数据同步任务的机制,那么客户端的读请求就可能在 follower 同步到 set x = 1 这一项任务之前就打到 follower,此时会取到 x 的老数据或者 x 不存在的响应,总之,读到的数据和客户端期待的结果产生了差距.
我们虽然不能满足让数据立即产生一致性,但是可以追求最终一致性。
可用性
上面描述的一致性问题都是本质都是因为数据是异步处理的,如果改成同步处理会怎么样呢?
- set x = 1 的写请求到达 master;
- master 将 x = 1 写入本机状态机;
- master 将 set x = 1 同步到所有 follower;
- 当 master 接收到所有 follower 同步成功的响应,确保数据在整个请求均同步完成后,才给客户端 ack;
- 客户端无论向集群中哪个节点发起读请求,都保证能拿到最新的数据.
这种方式保证了在数据未同步完成前,客户端会因为未拿到 ack 而陷入阻塞,不会发起读请求, 但是却带来了可用性的问题:
- 倘若集群中某个 follower 出现宕机, master 同步数据时会因为未集齐所有 follower 的响应, 而无法给客户端 ack,这样一个节点的问题就会被放大到导致整个系统不可用;
- 倘若某个 follower 的网络环境或者本机环境出现问题,它给出同步数据响应的时间出乎意料的长,那么整个系统的响应效率都会被其拖垮,这就是所谓的木桶效应.
怎么看待C和A的共存
我们如果强调 C 则舍弃了 A,突出 A 则违背了 C,这样必然导致对方成为了木桶效应中对系统最不利的那一块短板,显得无比眨扎眼.
实际上,一致性(C)和可用性(A)并非处于绝对的对立态势。它们之间存在着一种微妙的平衡,可以根据具体的需求进行调整和取舍。我们可以将这种平衡比喻为一个连续的滑动尺度,两端分别代表最强的一致性和最高的可用性,中间则是各种可能的平衡状态。根据应用的实际需求,我们可以移动这个滑动标尺来选择更偏向一致性还是更偏向可用性。
因此,我们的目标是在这个平衡尺度中寻找到最适合我们系统需求的位置或者说是系统的整体下限,以便在保持一定水平的一致性和可用性之间取得最佳平衡。所有的分布式共识算法,其实都是在尝试以不同的方式来做这样一件事情。