NOTE
3.5 分布式一致性模型
1. 分布式一致性模型是什么 - 不同的一致性模型解决了不同程度的一致性问题 2. 分布式一致性模型分类 2.1. 强一致性 - CAP.md中的C - 也叫线性一致性 2.2. 弱一致性 - 最终一致性 - 因果一致性 - 读你所写一致性 - 会话一致性 - 单调读一致性 - 单调写一致性 - 前
这是历史学习笔记,可能存在过时或不完整的理解。
1. 分布式一致性模型是什么
- 不同的一致性模型解决了不同程度的一致性问题
2. 分布式一致性模型分类

2.1. 强一致性
- CAP.md中的C
- 也叫线性一致性
2.2. 弱一致性
- 最终一致性
- 因果一致性
- 读你所写一致性
- 会话一致性
- 读你所写一致性
- 单调读一致性
- 单调写一致性
- 前缀读一致性
- 因果一致性
3. 线性一致性
3.1. 是什么
- 只要一个客户端成功完成写操作,所有客户端从数据库中读取数据必须能够看到刚刚写入的值

- 如果存储满足线性一致性,那么客户端进程可以把该存储当作
- 只有一个数据副本
- 所有的操作都是原子的
3.2. 使用场景
- 分布式锁和Leader选举:比如Leader选举本质上就是谁抢到了锁,谁就是Leader
- 唯一性保证:比如用户名必须唯一
- 跨多个通道的顺序性:比如RPC调用+消息队列
3.3. 实现
- 单Leader复制+一致性算法:
- 一致性算法解决了单Leader复制的脑裂和读取过期数据的问题
- 使用同步而不是异步复制
3.4. 问题
- 线性一致性就是牺牲了CAP中的A
4. 最终一致性
4.1. 是什么
- BASE.md中的E
- 最终一致性要求一旦更新成功,各个副本上的数据最终将达到完全一致的状态,但达到完全一致状态所需要的时间不能保障。

4.2. 问题
- 没有规定等待的时间
5. 因果一致性
5.1. 是什么
- 如果a、b进程有因果关系,那么a更新后,需要通知b进程

5.1.1. 全局与偏序
- 全序指给定两个数a,b,一定可以知道要么a>b,要么a<b
- 偏序指给定两个数a,b,可能a>b,可能a<b,也可能a和b不能比较
5.1.2. 因果关系
- 如果a是因,b是果,那么a happen before b而不能b happen before a
- 因果关系是一种偏序关系
- 线性一致性是一种全序关系
5.2. 实现
- 因果一致性序列号+全序广播
5.2.1. 因果一致性序列号
- 就是一个递增的ID,用于明确所有操作的全序
- 单Leader:由主库生成即可
- 多Leader:Lamport时钟
5.2.2. 全序广播
- 用于明确全序何时落地
- 通过单Leader多Follower机制,在Leader节点上对所有操作进行排序,从而决定了整个操作顺序,并将操作顺序进行广播
- 分布式节点间交换消息的协议,有两个属性
- 可靠性:消息不会丢失
- 有序性:发消息的顺序是怎样的,那么收消息的顺序就是怎样的
5.2.3. 全序广播的问题
- 如果吞吐量大于单Leader的处理量,那么如何扩展系统
- 出现Leader失效的情况,如何进行故障转移
6. 读你所写一致性
- 用户刚在leader写完数据,从leader读是可以读到的,但是立马从follower读,此时是读不到的

6.1. 实现
- 从Leader读
- 用户在更新后的一分钟内从Leader节点那里读取自己写入的数据,然后从Follower节点处读取其他用户写入的数据
- 缺点:仅仅适用于每个用户都仅仅修改自己数据的场景
- 时间戳机制
- 客户端记录最后一次写入的逻辑时间,从follower读的时候必须读取这个时间之后的数据,否则路由到其他节点或者等待时间。时间戳可以是逻辑时间或者系统时间
7. 会话一致性
7.1. 是什么

- 在一个会话期间可以保证读你所写一致性
8. 单调读一致性
8.1. 是什么
- leader同步给follower1但是没有同步给follower2
- 用户先从follower1读,取到了新数据;
- 再从follower2读,这个数据不存在了
- 单调读一致性保证如果某个进程读取到数据x的某个版本数据v2,那么系统所有后续的读取操作都不能看到比v2更老版本的数值,比如v1

8.2. 实现
- 同一个用户通过
hash(uid)打到同一个副本读取
9. 单调写一致性
9.1. 是什么
单调写一致性可以保证其多次写操作的序列化,如果没有这种保证,对于应用开发者来说是很难进行程序开发的。
10. 前缀读一致性
10.1. 是什么
- 用户1写入data1到leader1
- 用户2写入data2到leader2
- leader2同步data2给follower2
- 用户3从follower1读取没有data1
- 用户3从follower2读取有了data2
- leader1同步data1给follower1
- 用户3从follower1读取有了data1
10.2. 实现
- 确保任何因果相关的写入都写入相同的分区