auto commit

This commit is contained in:
CyC2018
2020-11-17 00:32:18 +08:00
parent f5ad47b470
commit 7e61fc1360
380 changed files with 2371 additions and 46715 deletions

View File

@ -1,33 +1,17 @@
# 分布式
<!-- GFM-TOC -->
* [分布式](#分布式)
* [数据库的唯一索引](#数据库的唯一索引)
* [Redis SETNX 指令](#redis--setnx-指令)
* [Redis RedLock 算法](#redis--redlock-算法)
* [Zookeeper 的有序节点](#zookeeper-的有序节点)
* [分布式事务](#二分布式事务)
* [2PC](#2pc)
* [本地消息表](#本地消息表)
* [CAP](#三cap)
* [一致性](#一致性)
* [可用性](#可用性)
* [分区容忍性](#分区容忍性)
* [权衡](#权衡)
* [BASE](#四base)
* [基本可用](#基本可用)
* [软状态](#软状态)
* [最终一致性](#最终一致性)
* [Paxos](#五paxos)
* [执行过程](#执行过程)
* [约束条件](#约束条件)
* [Raft](#六raft)
* [单个 Candidate 的竞选](#单个-candidate-的竞选)
* [多个 Candidate 竞选](#多个-candidate-竞选)
* [数据同步](#数据同步)
* [参考](#参考)
* [分布式](#分布式)
* [分布式锁](#一分布式锁)
* [分布式事务](#二分布式事务)
* [CAP](#三cap)
* [BASE](#四base)
* [Paxos](#五paxos)
* [Raft](#六raft)
* [参考](#参考)
<!-- GFM-TOC -->
# 分布式锁
## 分布式锁
在单机场景下可以使用语言的内置锁来实现进程同步但是在分布式场景下需要同步的进程可能位于不同的节点上那么就需要使用分布式锁
@ -38,7 +22,7 @@
1 0 可以用一个整型值表示也可以用某个数据是否存在表示
## 数据库的唯一索引
### 数据库的唯一索引
获得锁时向表中插入一条记录释放锁时删除这条记录唯一索引可以保证该记录只被插入一次那么就可以用这个记录是否存在来判断是否处于锁定状态
@ -48,7 +32,7 @@
- 只能是非阻塞锁插入失败直接就报错了无法重试
- 不可重入已经获得锁的进程也必须重新获取锁
## Redis SETNX 指令
### Redis SETNX 指令
使用 SETNXset if not exist指令插入一个键值对如果 Key 已经存在那么会返回 False否则插入成功并返回 True
@ -56,7 +40,7 @@ SETNX 指令和数据库的唯一索引类似,保证了只存在一个 Key 的
EXPIRE 指令可以为一个键值对设置一个过期时间从而避免了数据库唯一索引实现方式中释放锁失败的问题
## Redis RedLock 算法
### Redis RedLock 算法
使用了多个 Redis 实例来实现分布式锁这是为了保证在发生单点故障时仍然可用
@ -64,40 +48,40 @@ EXPIRE 指令可以为一个键值对设置一个过期时间,从而避免了
- 计算获取锁消耗的时间只有时间小于锁的过期时间并且从大多数N / 2 + 1实例上获取了锁才认为获取锁成功
- 如果获取锁失败就到每个实例上释放锁
## Zookeeper 的有序节点
### Zookeeper 的有序节点
### 1. Zookeeper 抽象模型
#### 1. Zookeeper 抽象模型
Zookeeper 提供了一种树形结构的命名空间/app1/p_1 节点的父节点为 /app1
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/aefa8042-15fa-4e8b-9f50-20b282a2c624.png" width="320px"> </div><br>
### 2. 节点类型
#### 2. 节点类型
- 永久节点不会因为会话结束或者超时而消失
- 临时节点如果会话结束或者超时就会消失
- 有序节点会在节点名的后面加一个数字后缀并且是有序的例如生成的有序节点为 /lock/node-0000000000它的下一个有序节点则为 /lock/node-0000000001以此类推
### 3. 监听器
#### 3. 监听器
为一个节点注册监听器在节点状态发生改变时会给客户端发送消息
### 4. 分布式锁实现
#### 4. 分布式锁实现
- 创建一个锁目录 /lock
- 当一个客户端需要获取锁时 /lock 下创建临时的且有序的子节点
- 客户端获取 /lock 下的子节点列表判断自己创建的子节点是否为当前子节点列表中序号最小的子节点如果是则认为获得锁否则监听自己的前一个子节点获得子节点的变更通知后重复此步骤直至获得锁
- 执行业务代码完成后删除对应的子节点
### 5. 会话超时
#### 5. 会话超时
如果一个已经获得锁的会话超时了因为创建的是临时节点所以该会话对应的临时节点会被删除其它会话就可以获得锁了可以看到这种实现方式不会出现数据库的唯一索引实现方式释放锁失败的问题
### 6. 羊群效应
#### 6. 羊群效应
一个节点未获得锁只需要监听自己的前一个子节点这是因为如果监听所有的子节点那么任意一个子节点状态改变其它所有子节点都会收到通知羊群效应一只羊动起来其它羊也会一哄而上而我们只希望它的后一个子节点收到通知
# 分布式事务
## 分布式事务
指事务的操作位于不同的节点上需要保证事务的 ACID 特性
@ -108,19 +92,19 @@ Zookeeper 提供了一种树形结构的命名空间,/app1/p_1 节点的父节
- 锁问题的关键在于进程操作的互斥关系例如多个进程同时修改账户的余额如果没有互斥关系则会导致该账户的余额不正确
- 而事务问题的关键则在于事务涉及的一系列操作需要满足 ACID 特性例如要满足原子性操作则需要这些操作要么都执行要么都不执行
## 2PC
### 2PC
两阶段提交Two-phase Commit2PC通过引入协调者Coordinator来协调参与者的行为并最终决定这些参与者是否要真正执行事务
### 1. 运行过程
#### 1. 运行过程
#### 1.1 准备阶段
##### 1.1 准备阶段
协调者询问参与者事务是否执行成功参与者发回事务执行结果询问可以看成一种投票需要参与者都同意才能执行
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/44d33643-1004-43a3-b99a-4d688a08d0a1.png" width="550px"> </div><br>
#### 1.2 提交阶段
##### 1.2 提交阶段
如果事务在每个参与者上都执行成功事务协调者发送通知让参与者提交事务否则协调者发送通知让参与者回滚事务
@ -128,25 +112,25 @@ Zookeeper 提供了一种树形结构的命名空间,/app1/p_1 节点的父节
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/d2ae9932-e2b1-4191-8ee9-e573f36d3895.png" width="550px"> </div><br>
### 2. 存在的问题
#### 2. 存在的问题
#### 2.1 同步阻塞
##### 2.1 同步阻塞
所有事务参与者在等待其它参与者响应的时候都处于同步阻塞等待状态无法进行其它操作
#### 2.2 单点问题
##### 2.2 单点问题
协调者在 2PC 中起到非常大的作用发生故障将会造成很大影响特别是在提交阶段发生故障所有参与者会一直同步阻塞等待无法完成其它操作
#### 2.3 数据不一致
##### 2.3 数据不一致
在提交阶段如果协调者只发送了部分 Commit 消息此时网络发生异常那么只有部分参与者接收到 Commit 消息也就是说只有部分参与者提交了事务使得系统数据不一致
#### 2.4 太过保守
##### 2.4 太过保守
任意一个节点失败就会导致整个事务失败没有完善的容错机制
## 本地消息表
### 本地消息表
本地消息表与业务数据表处于同一个数据库中这样就能利用本地事务来保证在对这两个表的操作满足事务特性并且使用了消息队列来保证最终一致性
@ -157,31 +141,31 @@ Zookeeper 提供了一种树形结构的命名空间,/app1/p_1 节点的父节
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/476329d4-e2ef-4f7b-8ac9-a52a6f784600.png" width="740px"> </div><br>
# CAP
## CAP
分布式系统不可能同时满足一致性CConsistency可用性AAvailability和分区容忍性PPartition Tolerance最多只能同时满足其中两项
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/a14268b3-b937-4ffa-a34a-4cc53071686b.jpg" width="450px"> </div><br>
## 一致性
### 一致性
一致性指的是多个数据副本是否能保持一致的特性在一致性的条件下系统在执行数据更新操作之后能够从一致性状态转移到另一个一致性状态
对系统的一个数据更新成功之后如果所有用户都能够读取到最新的值该系统就被认为具有强一致性
## 可用性
### 可用性
可用性指分布式系统在面对各种异常时可以提供正常服务的能力可以用系统可用时间占总时间的比值来衡量4 9 的可用性表示系统 99.99% 的时间是可用的
在可用性条件下要求系统提供的服务一直处于可用的状态对于用户的每一个操作请求总是能够在有限的时间内返回结果
## 分区容忍性
### 分区容忍性
网络分区指分布式系统中的节点被划分为多个区域每个区域内部可以通信但是区域之间无法通信
在分区容忍性条件下分布式系统在遇到任何网络分区故障的时候仍然需要能对外提供一致性和可用性的服务除非是整个网络环境都发生了故障
## 权衡
### 权衡
在分布式系统中分区容忍性必不可少因为需要总是假设网络是不可靠的因此CAP 理论实际上是要在可用性和一致性之间做权衡
@ -190,24 +174,24 @@ Zookeeper 提供了一种树形结构的命名空间,/app1/p_1 节点的父节
- 为了保证一致性CP不能访问未同步完成的节点也就失去了部分可用性
- 为了保证可用性AP允许读取所有节点的数据但是数据可能不一致
# BASE
## BASE
BASE 是基本可用Basically Available软状态Soft State和最终一致性Eventually Consistent三个短语的缩写
BASE 理论是对 CAP 中一致性和可用性权衡的结果它的核心思想是即使无法做到强一致性但每个应用都可以根据自身业务特点采用适当的方式来使系统达到最终一致性
## 基本可用
### 基本可用
指分布式系统在出现故障的时候保证核心可用允许损失部分可用性
例如电商在做促销时为了保证购物系统的稳定性部分消费者可能会被引导到一个降级的页面
## 软状态
### 软状态
指允许系统中的数据存在中间状态并认为该中间状态不会影响系统整体可用性即允许系统不同节点的数据副本之间进行同步的过程存在时延
## 最终一致性
### 最终一致性
最终一致性强调的是系统中所有的数据副本在经过一段时间的同步后最终能达到一致的状态
@ -215,7 +199,7 @@ ACID 要求强一致性,通常运用在传统的数据库系统上。而 BASE
在实际的分布式场景中不同业务单元和组件对一致性的要求是不同的因此 ACID BASE 往往会结合在一起使用
# Paxos
## Paxos
用于达成共识性问题即对多个节点产生的值该算法能保证只选出唯一一个值
@ -227,11 +211,11 @@ ACID 要求强一致性,通常运用在传统的数据库系统上。而 BASE
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/b988877c-0f0a-4593-916d-de2081320628.jpg"/> </div><br>
## 执行过程
### 执行过程
规定一个提议包含两个字段[n, v]其中 n 为序号具有唯一性v 为提议值
### 1. Prepare 阶段
#### 1. Prepare 阶段
下图演示了两个 Proposer 和三个 Acceptor 的系统中运行该算法的初始过程每个 Proposer 都会向所有 Acceptor 发送 Prepare 请求
@ -243,13 +227,13 @@ ACID 要求强一致性,通常运用在传统的数据库系统上。而 BASE
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/fb44307f-8e98-4ff7-a918-31dacfa564b4.jpg"/> </div><br>
如果 Acceptor 接收到一个 Prepare 请求包含的提议为 [n2, v2]并且之前已经接收过提议 [n1, v1]如果 n1 > n2那么就丢弃该提议请求否则发送 Prepare 响应 Prepare 响应包含之前已经接收过的提议 [n1, v1]设置当前接收到的提议为 [n2, v2]并且保证以后不会再接受序号小于 n2 的提议
如果 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 响应设置当前接收到的提议为 [n=4, v=5]并且保证以后不会再接受序号小于 4 的提议Acceptor Y 类似
如下图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 响应设置当前接收到的提议为 [n=4, v=5]并且保证以后不会再接受序号小于 4 的提议Acceptor Y 类似
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/2bcc58ad-bf7f-485c-89b5-e7cafc211ce2.jpg"/> </div><br>
### 2. Accept 阶段
#### 2. Accept 阶段
当一个 Proposer 接收到超过一半 Acceptor Prepare 响应时就可以发送 Accept 请求
@ -259,33 +243,33 @@ Proposer B 过后也收到了两个 Prepare 响应,因此也开始发送 Accep
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/9b838aee-0996-44a5-9b0f-3d1e3e2f5100.png"/> </div><br>
### 3. Learn 阶段
#### 3. Learn 阶段
Acceptor 接收到 Accept 请求时如果序号大于等于该 Acceptor 承诺的最小序号那么就发送 Learn 提议给所有的 Learner Learner 发现有大多数的 Acceptor 接收了某个提议那么该提议的提议值就被 Paxos 选择出来
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/bf667594-bb4b-4634-bf9b-0596a45415ba.jpg"/> </div><br>
## 约束条件
### 约束条件
### 1\. 正确性
#### 1\. 正确性
指只有一个提议值会生效
因为 Paxos 协议要求每个生效的提议被多数 Acceptor 接收并且 Acceptor 不会接受两个不同的提议因此可以保证正确性
### 2\. 可终止性
#### 2\. 可终止性
指最后总会有一个提议生效
Paxos 协议能够让 Proposer 发送的提议朝着能被大多数 Acceptor 接受的那个提议靠拢因此能够保证可终止性
# Raft
## Raft
Raft 也是分布式一致性协议主要是用来竞选主节点
- [Raft: Understandable Distributed Consensus](http://thesecretlivesofdata.com/raft)
## 单个 Candidate 的竞选
### 单个 Candidate 的竞选
有三种节点FollowerCandidate LeaderLeader 会周期性的发送心跳包给 Follower每个 Follower 都设置了一个随机的竞选超时时间一般为 150ms\~300ms如果在这个时间内没有收到 Leader 的心跳包就会变成 Candidate进入竞选阶段
@ -305,7 +289,7 @@ Raft 也是分布式一致性协议,主要是用来竞选主节点。
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/111521118640738.gif"/> </div><br>
## 多个 Candidate 竞选
### 多个 Candidate 竞选
- 如果有多个 Follower 成为 Candidate并且所获得票数相同那么就需要重新开始投票例如下图中 Node B Node D 都获得两票需要重新开始投票
@ -315,7 +299,7 @@ Raft 也是分布式一致性协议,主要是用来竞选主节点。
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/111521119368714.gif"/> </div><br>
## 数据同步
### 数据同步
- 来自客户端的修改都会被传入 Leader注意该修改还未被提交只是写入日志中
@ -333,7 +317,7 @@ Raft 也是分布式一致性协议,主要是用来竞选主节点。
<div align="center"> <img src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/111550414182638.gif"/> </div><br>
# 参考
## 参考
- 倪超. Paxos ZooKeeper : 分布式一致性原理与实践 [M]. 电子工业出版社, 2015.
- [Distributed locks with Redis](https://redis.io/topics/distlock)
@ -346,10 +330,3 @@ Raft 也是分布式一致性协议,主要是用来竞选主节点。
- [NEAT ALGORITHMS - PAXOS](http://harry.me/blog/2014/12/27/neat-algorithms-paxos/)
- [Paxos By Example](https://angus.nyc/2012/paxos-by-example/)
<div align="center"><img width="320px" src="https://cs-notes-1256109796.cos.ap-guangzhou.myqcloud.com/githubio/公众号二维码-2.png"></img></div>