分布式(CS-Notes)

目录

1  分布式锁

1.1  数据库的唯一索引

1.2  Redis 的 SETNX 指令

1.3  Redis 的 RedLock 算法

2  Zookeeper 的有序节点

1. Zookeeper 抽象模型

2. 节点类型

3. 监听器

4. 分布式锁实现

5. 会话超时

6. 羊群效应

2  分布式事务

2PC

1. 运行过程

2. 存在的问题

本地消息表

3  CAP

一致性

可用性

分区容忍性

权衡

4  BASE

4.1  基本可用

4.2  软状态

4.3  最终一致性

5  Paxos

5.1  执行过程

1. Prepare 阶段

2. Accept 阶段

3. Learn 阶段

约束条件

1. 正确性

2. 可终止性

6  Raft

6.1  单个 Candidate 的竞选

6.2  多个 Candidate 竞选

数据同步

参考


1  分布式锁

在单机场景下,可以使用语言的内置锁来实现进程同步。但是在分布式场景下,需要同步的进程 可能位于不同的节点上,那么就需要使用分布式锁

阻塞锁通常使用互斥量来实现:

  • 互斥量为 0 表示有其它进程在使用锁,此时处于锁定状态
  • 互斥量为 1 表示未锁定状态

1 和 0 可以用一个整型值表示,也可以用某个数据是否存在表示。

1.1  数据库的唯一索引

获得锁时向表中插入一条记录释放锁时删除这条记录唯一索引可以保证该记录只被插入一次,那么就可以用这个记录是否存在来判断是否处于锁定状态

唯一索引是不允许其中任何两行具有相同索引值的索引。当现有数据中存在重复的键值时,大多数数据库不允许将新创建的唯一索引与表一起保存。数据库还可能防止添加将在表中创建重复键值的新数据。例如,如果在 employee 表中职员的姓 (lname) 上创建了唯一索引,则任何两个员工都不能同姓

存在以下几个问题:

  • 锁 没有失效时间,解锁失败的话 其它进程无法再获得该锁。
  • 只能是非阻塞锁,插入失败直接就报错了,无法重试。
  • 不可重入,已经获得锁的进程也必须重新获取锁。

 

1.2  Redis 的 SETNX 指令

使用 SETNX(set if not exist)指令插入一个键值对,如果 Key 已经存在,那么会返回 False;否则插入成功并返回 True。

 

SETNX 指令和数据库的唯一索引类似,保证了只存在一个 Key 的键值对,那么可以用一个 Key 的键值对是否存在来判断是否存于锁定状态

 

EXPIRE 指令可以为一个键值对 设置一个过期时间,从而避免了 数据库唯一索引实现方式中 释放锁失败的问题

 

1.3  Redis 的 RedLock 算法

使用了多个 Redis 实例来实现分布式锁,这是为了保证在发生单点故障时仍然可用。

  • 尝试从 N 个互相独立 Redis 实例获取锁;
  • 计算 获取锁消耗的时间,只有当这个时间 小于 锁的过期时间,并且从大多数(N / 2 + 1)实例上获取了锁,那么就认为锁获取成功了
  • 如果锁获取失败,就到每个实例上释放锁。

 

 

 

2  Zookeeper 的有序节点

1. Zookeeper 抽象模型

Zookeeper 提供了一种树形结构的命名空间,/app1/p_1 节点的父节点 为 /app1。

2. 节点类型

  • 永久节点:不会因为会话结束或者超时而消失;
  • 临时节点如果会话结束或者超时就会消失;
  • 有序节点:会在节点名的后面  加一个数字后缀,并且是有序的,例如生成的有序节点为 /lock/node-0000000000,它的下一个有序节点则为 /lock/node-0000000001,以此类推。

3. 监听器

为一个节点注册监听器,从而 节点状态发生改变时,会给客户端发送消息

4. 分布式锁实现

  • 创建一个锁目录 /lock;
  • 当一个客户端需要获取锁时,在 /lock 下创建临时的且有序的子节点
  • 客户端获取 /lock 下的子节点列表,判断自己创建的子节点是否为当前子节点列表中序号最小的子节点,如果是则认为获得锁;否则监听自己的前一个子节点,获得子节点的变更通知后重复此步骤直至获得锁;
  • 执行业务代码,完成后,删除对应的子节点。

5. 会话超时

如果一个已经获得锁的会话超时了,因为创建的是临时节点,所以该会话对应的临时节点会被删除,其它会话就可以获得锁了。可以看到,Zookeeper 分布式锁不会出现数据库的唯一索引实现的分布式锁释放锁失败问题。

6. 羊群效应

一个节点未获得锁,只需要监听自己的前一个子节点。这是因为如果监听所有的子节点,那么任意一个子节点状态改变,其它所有子节点都会收到通知(羊群效应),而我们只希望 它的后一个子节点 收到通知

避免了传递太多的消息。每次一个结点改变了,只有他后面的一个结点收到通知。


 

 

 

2  分布式事务

事务的操作 位于不同的节点上,需要保证事务的 ACID 特性。

例如在下单场景下,库存订单如果不在同一个节点上,就涉及分布式事务

2PC

两阶段提交Two-phase Commit,2PC),通过引入协调者(Coordinator)来协调参与者的行为,并最终决定这些参与者是否要真正执行事务

1.协调服务器 询问 所有的参与服务器,事务是否执行成功。各个参与服务器将事务执行结果 发送给 协调服务器。(注意:此时事务并未在各个参与服务器上提交)

2.若所有的参与服务器都成功执行了事务。这时候协调服务器 会给所有参与服务器发通知,让他们在自己的服务器上提交事务

1. 运行过程

1.1 准备阶段

协调者询问参与者 事务是否执行成功,参与者 发回事务执行结果

1.2 提交阶段

如果事务在每个参与者上都执行成功事务协调者发送通知让参与者提交事务;否则,协调者发送通知让参与者回滚事务

需要注意的是,在准备阶段参与者 执行了事务但是还未提交。只有在提交阶段 接收到 协调者发来的通知后,才进行提交或者回滚

2. 存在的问题

2.1 同步阻塞

所有事务参与者等待其它参与者响应的时候,都处于 同步阻塞状态,无法进行其它操作。

2.2 单点问题

协调者在 2PC 中起到非常大的作用。如果协调组发生故障 将会造成很大影响。特别是在阶段二发生故障,所有参与者会一直等待,无法完成其它操作。

2.3 数据不一致

在阶段二,如果协调者只发送了部分 Commit 消息,此时网络发生异常,那么只有部分参与者接收到 Commit 消息,也就是说只有部分参与者提交了事务,使得系统数据不一致(有的参与服务器提交了事务,有的参与服务器没提交事务)。

2.4 太过保守

任意一个节点失败就会导致整个事务失败,没有完善的容错机制。

 

 

本地消息表

本地消息表与业务数据表处于同一个数据库中,这样就能利用本地事务来保证在对这两个表的操作满足事务特性,并且使用了消息队列来保证最终一致性。

  1. 分布式事务操作的一方完成写业务数据的操作之后,向本地消息表发送一个消息。本地事务能保证这个消息一定会被写入本地消息表中
  2. 之后将本地消息表中的消息转发到消息队列中。如果转发成功,则将消息从本地消息表中删除;否则继续重新转发
  3. 分布式事务操作的另一方 从消息队列中 读取一个消息,并执行消息中的操作。

https://blog.csdn.net/Rex_WUST/article/details/95303172


 

 

3  CAP

分布式系统不可能同时满足一致性(C:Consistency)、可用性(A:Availability)和分区容忍性(P:Partition Tolerance),最多只能同时满足其中两项

一致性

一致性指的是多个数据副本是否能保持一致的特性。在一致性的条件下,系统在执行数据更新操作之后能够从一致性状态转移到另一个一致性状态

系统的一个数据更新成功之后,如果所有用户 都能够读取到最新的值,该系统就被认为具有强一致性

可用性

可用性指 分布式系统 在面对各种异常时 可以提供正常服务的能力,可以用系统可用时间总时间的比值来衡量。4 个 9 的可用性 表示 系统 99.99% 的时间是可用的。

在可用性条件下,要求系统提供的服务一直处于可用的状态,对于用户的每一个操作请求总是能够 在有限的时间内 返回结果

分区容忍性

网络分区指 分布式系统中的节点 被划分为多个区域每个区域内部可以通信,但是区域之间无法通信

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

权衡

在分布式系统中,分区容忍性 必不可少,因为需要总是假设网络是不可靠的。因此,CAP 理论实际上是要在可用性一致性之间 做权衡。

可用性和一致性往往是冲突的,很难使它们同时满足。在多个节点之间进行数据同步时,

  • 为了保证一致性(CP),不能访问 未同步完成的节点,也就失去了部分可用性;
  • 为了保证可用性(AP),允许读取 所有节点的数据,但是数据可能不一致。

 

4  BASE

BASE 是基本可用(Basically Available)软状态(Soft State)最终一致性(Eventually Consistent)三个短语的缩写。

BASE 理论是对 CAP 中一致性和可用性权衡的结果,它的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性

 

4.1  基本可用

指分布式系统在出现故障的时候,保证核心可用,允许损失部分可用性

例如,电商在做促销时,为了保证购物系统的稳定性,部分消费者可能会被引导到一个降级的页面

 

4.2  软状态

允许系统中的数据 存在中间状态,并认为该中间状态不会影响系统整体可用性。即允许系统不同节点的数据副本之间 进行同步的过程存在时延

 

4.3  最终一致性

最终一致性强调的是系统中所有的数据副本在经过一段时间的同步后,最终能达到一致的状态

ACID 要求强一致性,通常运用在传统的数据库系统上。而 BASE 要求最终一致性,通过牺牲强一致性 来达到可用性,通常运用在大型分布式系统中。

在实际的分布式场景中,不同业务单元和组件对一致性的要求是不同的,因此 ACID 和 BASE 往往会结合在一起使用。


 

 

 

5  Paxos

用于达成共识性问题,即对多个节点产生的值,该算法能保证只选出 唯一一个值

主要有三类节点:

  • 提议者(Proposer):提议一个值;
  • 接受者(Acceptor):对每个提议进行投票;
  • 告知者(Learner):被告知 投票的结果不参与 投票过程

 

5.1  执行过程

规定一个提议包含两个字段:[n, v],其中 n序号(具有唯一性)v 提议值

1. Prepare 阶段

下图演示了两个 Proposer 和三个 Acceptor 的系统中运行该算法的初始过程,每个 Proposer 都会向所有 Acceptor 发送 Prepare 请求。


 

当 Acceptor 接收到一个 Prepare 请求,包含的提议为 [n1, v1],并且之前还未接收过 Prepare 请求,那么发送一个 Prepare 响应设置当前接收到的提议为 [n1, v1],并且保证以后不会再接受 序号小于 n1 的提议

例子如下图Acceptor X 在收到 [n=2, v=8] 的 Prepare 请求时,由于之前没有接收过提议,因此就发送一个 [no previous] 的 Prepare 响应,设置当前接收到的提议为 [n=2, v=8],并且保证以后不会再接受序号 小于 2 的提议。其它的 Acceptor 类似。


 

如果 Acceptor 接收到一个 Prepare 请求,包含的提议为 [n2, v2],并且之前已经接收过提议 [n1, v1]。如果 n1 > n2,那么就丢弃该提议请求;

否则,发送 Prepare 响应,该 Prepare 响应包含之前已经接收过的提议 [n1, v1]设置当前接收到的提议为 [n2, v2],并且保证以后不会再接受序号小于 n2 的提议

例子如下图Acceptor Z 收到 Proposer A 发来的 [n=2, v=8] 的 Prepare 请求,由于之前已经接收过 [n=4, v=5] 的提议,并且 n > 2,因此就抛弃该提议请求

Acceptor X 收到 Proposer B 发来的 [n=4, v=5] 的 Prepare 请求,因为之前接收到的提议为 [n=2, v=8],并且 2 <= 4,因此就发送 [n=2, v=8] 的 Prepare 响应( Prepare 响应包含之前已经接收过的提议设置当前接收到的提议为 [n=4, v=5],并且保证以后不会再接受序号小于 4 的提议。Acceptor Y 类似。

 

2. Accept 阶段

当一个 Proposer 接收到超过一半 Acceptor 的 Prepare 响应时,就可以发送 Accept 请求

Proposer A 接收到两个 Prepare 响应之后(总共发了3个请求,现在收到了两个响应。超过一半了),就发送 [n=2, v=8] Accept 请求该 Accept 请求会被所有 Acceptor 丢弃,因为此时所有 Acceptor 都保证不接受 序号小于 4 的提议

Proposer B 过后也收到了两个 Prepare 响应,因此也开始发送 Accept 请求。需要注意的是,Accept 请求的 v  需要取它收到的最大提议编号对应的 v 值,也就是 8。因此它发送 [n=4, v=8] 的 Accept 请求

 

3. Learn 阶段

Acceptor 接收到 Accept 请求时,如果序号 大于等于 该Acceptor 承诺的最小序号,那么就发送 Learn 提议所有的 Learner。当 Learner 发现有大多数的 Acceptor 接收了某个提议,那该提议的提议值就被 Paxos 选择出来

约束条件

1. 正确性

只有一个提议值会生效。

因为 Paxos 协议要求每个生效的提议被多数 Acceptor 接收,并且 Acceptor 不会接受两个不同的提议,因此可以保证正确性。

2. 可终止性

指最后总会有一个提议生效。

Paxos 协议能够让 Proposer 发送的提议 朝着能被大多数 Acceptor 接受的那个提议靠拢,因此能够保证可终止性


 

6  Raft

Raft 也是分布式一致性协议,主要是用来竞选 主节点

6.1  单个 Candidate 的竞选

有三种节点:FollowerCandidate Leader

Leader周期性地发送心跳包Follower

每个 Follower 都设置了一个随机的竞选超时时间,一般为 150ms~300ms,如果在这个时间内 没有收到 Leader 的心跳包,就会变成 Candidate,进入竞选阶段

 

  • 下图展示一个分布式系统的最初阶段,此时只有 Follower  没有 LeaderNode A 等待一个随机的竞选超时时间之后,没收到 Leader 发来的心跳包,因此进入竞选阶段。(注意成为候选人,会自己先给自己投一票。)

 

 

  • 此时 Node A 发送 投票请求 给其它所有节点。

 

 

  • 其它节点会对请求进行回复,如果超过一半的节点回复了,那么该 Candidate 就会变成 Leader

 

 

  • 之后 Leader 会周期性地发送心跳包给 Follower。Follower 接收到心跳包,会重新开始计时


 

 

6.2  多个 Candidate 竞选

  • 如果有多个 Follower 成为 Candidate,并且所获得票数相同,那么就需要重新开始投票。例如下图中 Node B Node D 都获得两票,需要重新开始投票。(P.S.下面的例子中,Node B Node D同时等待超时, 同时成为了候选人)

 

  • 由于每个节点设置的随机竞选超时时间不同,因此下一次再次出现多个 Candidate 并获得同样票数的概率很低。(这一次,NodeA 先等待超时,先成为了候选人)


 

 

数据同步

  • 来自客户端的修改都会被传入 Leader。注意该修改 还未被提交只是写入 日志 中

 

 

  • Leader 会把修改 复制到所有 Follower

 

 

  • Leader 会等待大多数的 Follower 也进行了修改,然后才将修改提交

 

 

  • 此时 Leader 通知 所有的 Follower,让它们也提交修改。然后 所有节点的值 达成一致。


参考

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值