青训营 浅谈分布式一致性协议
概述
2022の夏天,半壶水响叮当的我决定充实一下自我
一、内容介绍
青训营
总述
- 什么是一致性协议
- 以 Raft 为例子了解一致性协议是如何工作的
- 了解如何使用一致性协议构建一个 KV 系统
- 了解一致性协议的发展方向
远程过程调用(RPC)
- 分布式系统中通常将不同组件,或者不同节点的交互使用 RPC 的方式进行封装,在调用方的视角一次远程过程调用不需要关心如何对请求和响应进行编码,也不用关心具体的网络传输。
状态机(State Machine)
- 一种编程架构,状态机只取决于当前的状态与的输入,确定下一个状态
并发/并行
- 并发:多个任务可以在重叠的实践中启动、运行、完成,并发不一定意味着并行,可以通过切换的方式做到在一个执行单元上实现并发任务
- 并行:真正的多个任务同时运行,如多核CPU
容错
- 通常指一种软件架构,架构可以容许一定数目的节点失效,同时保证系统正常或降级运行
高可用
- 指系统可以达到较高的可用时间,如系统保证一年中只有若干分钟不可用,通常以 SLA(Service-level agreement) 进行描述,容错架构是实现高可用系统的一种方式
二、分布式系统
为什么需要分布式系统
对分布式系统的要求
介绍KV案例
2.1 分布式系统面临的挑战
- 数据规模越来越大
- 服务的可用性要求越来越高
- 快速迭代的业务要求系统足够易用
- 各种各样的错误
- 网络
- 磁盘
- CPU
2.2 理想中的分布式系统
- 高性能:可拓展、低时延、高吞吐
- 正确: -致性、易于理解
- 可靠:容错、高可用
2.3 从HDFS开始
2.4 案例- KV
- 从最简单机KV开始
- 接口:
- Get(key) -> value
- BatchPut([k1, k2, ..]. [v1, v2...])
- 第一次实现
- RPC
- DB Engine
- 可靠性:
- 容错?
- 高可用?
- 正确性:
- 单进程,所有操作顺序执行
小结
- 背景:数据规模的不断增加,我们需要大规模分布式系统
- 维度:对于一个分布式系统,希望能有哪些特征
- 从KV入手,看看我们如何满足分布式系统的要求
三、一致性与共识算法
什么是一致性
什么是共识算法
3.1 从复制开始
- 既然一台机器会挂
- 如果两个副本都能接受请求
3.2 如何复制
- 主副本定期拷贝全量数据到从副本
- 主副本拷贝操作到从副本
3.3 如何复制操作
- 主副本把所有的操作打包成Log/日志
- 所有的Log写入都是持久化的,保存在磁盘上
- 应用包装成状态机,只接收Log作为Input
- 主副本确认Log已经成功写入到副本机器上,当状态机apply后,返回客户端
3.4 关于读操作
- 读操作
- 方案一:直接读状态机,要求写操作进入状态机后再返回client
- 方案二:写操作复制完成后直接返回,读操作Block等待所有pending log进入状态机
- 如果不遵循上述两周方案呢?
- 可能存在刚刚写入的值读不到的情况(在Log中)
3.5 什么是一致性
- 对于我们的KV
- 像操作一台机器样
- 要读到最近写入的值
- 像操作一台机器样
- 致性是一种模型(或语义)
- 来约定一个分布式系统如何向外界(应用)提供服务
- KV中常见的一致性模型
- 最终一致性: 读取可能暂时读不到但是总会读到
- 线性一致性: 最严格,线性执行
- 一致性的分类
- 经常与应用本身有关
- Linearizability/线性化 是最理想的
3.5.1 一致性协议的限制
-
对于分布式系统
- 拓展性:写入性能不能水平拓展
- 性能:强 Leader 的一致性协议跨地域部署时带来的额外网络开销
-
对于 KV 系统,解决方案一般是通过分片的方式水平拆组
- 引入了事务的概念
- 常见二阶段提交
3.6 复制协议当失效发生
- 当主副本失效
- 手动切换
- 容错?
- 不,我们的服务还是停了
- 高可用?
- 也许,取决于我们从发现到切换的过程的有多快
- 正确?
- 操作只从一台机器上发起
- 所有操作返回前都已经复制到另一台机器了
3.6.1 复制协议-小结
- 当主副本失效时,为了使得算法简单
- 我们人肉切换,只要足够快
- 我们还是可以保证较高的可用性。
- 我们人肉切换,只要足够快
- 但是如何保证主副本是真的失效了呢?
- 在切换的过程中,主副本又开始接收client端的请求
- 两个主副本显然是不正确的,log 会被覆盖写掉
- 我们希望算法能在这种场景下仍然保持正确
- 要是增加到三个节点呢?
- 每次都等其他节点操落盘性能较差
- 能不能允许少数节点挂了的情况下,仍然可以工作
- falut- tolerance/耐受性
3.7 共识算法
- 什么是共识算法
"The consensus problem requires agreement among a number of processes (or agents) for a single data value. Some of the processes (agents) may fail or be unreliable in other ways,so consensus protocols must be fault tolerant or resilient"
"协商一致问题需要多个进程(或代理)达成一致。一个单一的数据值。有些过程(代理)可能在其他方面失败或不可靠,因此,协商一致的协议必须具有容错性或弹性。"
简而言之一个值一旦确定, 所有人都认同。
- 有文章证明是一个不可能的任务(FLP impossibility/有限差分不可能)
In this paper, we show the surprising result that no completely asynchronous consensus protocol can tolerate even a single unannounced process death. We do not consider Byzantine failures, and we assume that the message system is reliableit delivers all messages correctly and exactly once."
"在本文中,我们展示了一个令人惊讶的结果:没有一个完全异步的协商一致协议能够容忍一个单一的未经宣布的进程死亡。我们不考虑拜占庭式的失败,我们假设消息系统是可靠的,它能正确、准确地传递所有消息一次。"
-- JACM 85 [1]
-
错误总是发生
- Non-Byzantine fault/非拜占庭断层
-
错误类型很多
- 网络断开,分区,缓慢,重传,乱序
- CPU、I0都机会停住
-
容错(falute-tolerance)
-
共识协议不等于一致性
- 应用层面不同的一致性,都可以用共识协议来实现
- 比如可以故意返回旧的值
- 简单的复制协议也可以提供线性一致性
- 应用层面不同的一致性,都可以用共识协议来实现
-
一般讨论共识协议时提到的一致性,都指线性一致性
- 因为弱一致性往往可以使用相对简单的复制算法实现
3.8 发展方向
-
一致性协议作为系统
- 分布式日志:暴露日志的接口提供给上层应用,提供灵活高可用的一致性服务
-
高性能一致性协议
- 低延时:结合 RDMA 网络以及可编程交换机,实现 us 级别操作。
- LeaderLess:节点就地提交,降低 WAN 网络下 RTT 开销
-
Paxos 与 Raft 的相互关联
- 移植 Paxos 的研究到成熟
小结
- 使用副本的方式设计了KV
- 了解了什么是一致性
- 了解了什么是共识算法
- 设计一个正确且容错的一致性是一个难题
四、从Raft入手
Paxos跟Raft
了解Raft基本工作原理
4.1. Paxos
4.2. 案例:Raft
-
Raft 是在 paxos 的基础上的基础上,着重于易于理解
- 协议接口直接暴露 Log 给用户
- 强 Leader 简化 Paxos 中的二阶段
- 使用随机事件简化选主逻辑
-
Raft 的基本工作原理
- 各个节点的角色
- Log 同步
- 失效节点如何恢复 Log
- 如何选举新 Leader
- Term 以及安全性的保证
-
Raft 在工程中的优化
- Prevote 的应用,防止离群 Leader 重加入时引发的切主
4.3. 复制状态机(RSM)
- RSM (replicated state machine/复制状态机)
- Raft中所有的 consensus/一致性 都是直接使用Log作为载体
- Commited Index/逗号索引
- 一旦 Raft更新 Commited Index/推荐索引 ,意味着这个Index前的所有Log都可以提交给状态机了
- Commited Index是不持久化的,状态机也是volatile的,重启后从第一条Log开始
4.4. Raft角色
4.4.1 Raft整体流程
4.5. Raft日志复制
4.6. Raft从节点失效
4.7. Raft Term
- 每个Leader服务于一个term
- 每个term至多只有一个leader
- 每个节点存储当前的term
- 每个节点term从-开始,只增不减
- 所有rpc的request reponse都携带term
- 只commit本term内的log
4.8. Raft主节点失效
4.9. Raft Leader failure
4.10. Raft安全性-同Term
4.10.1 Raft安全性-跨Term
4.10.2 Raft安全性验证
小结
- 了解了Raft的基本工作原理
- 简单讨论了Raft正确性
五、实现细节以及未来
使用Raft构建我们的KV系统
了解共识算法的研究方向
5.1 案例 - KV
- 利用Raft算法,重新打造我们的KV
- Raft不保证一直有一个leader
- 只保证一个term至多有一个leader
- 可能存在多个term的leader
- Split- brain/脑裂
- 多个副本只有单个副本可以提供服务
- 服务无法水平拓展
- 增加更多Raft组
- 如果操作跨Raft组
5.2 回到共识算法
- Raft:关于 Log/日志
- 论文中就给出的方案,当过多的Log占用后,启动snapshot,替换掉Log
- 如果对于持久化的状态机,如何快速的产生Snapshot
- 多组Raft的应用中,Log如何合流
- 关于configuration change/配置变化
- 论文中给出的 joint consensus/联合共识 以及单一节 点变更两种方案
Raft是正确的,但是在工程世界呢?
- 真实世界中不是所有的错误都是完美fail-stop的
- cloudflare的case, etcd 在partial network'下,outage 了6个小时
- 高性能
- 数据中心网络100G,时延约为几个us
- RDMA网卡以及 programable switch/可编程交换机 的应用
- 我们想要的是:
- us级别的共识,以及us级别的容错
- HovercRaft/气垫船
- P4 programable switch:IP multicast
- Mu
- Use one sided RDMA/使用单边RDMA
- pull based heartbeat instead of push-based/以拉动为基础的心跳而不是以推为基础
- 多节点提交(Leaderless)
- 节点跨地域,导致节点间的RTT(Round Trip Time/往返时间)很大
- EPaxos
- 使用了冲突图的方式来允许并行Commit
- 不冲突的情况下1 RTT提交时间
5.3 共识算法的未来
- 共识算法作为一个系统
- 多数分布式系统都选择共识算法作为底座
- 不同一致性协议有不同的特性
- Virtual consensus in delos
- 对外暴露一致性的LOG作为借口
- 内部对于LOG可以选择不同的实现
小结
- 了解到了Raft如何应用在KV中
- 也了解到了单一的共识算法有其局限性
- 在工程实践中,需要对其进行一定的优化
- 最后,了解到了一致性协议当前的研究热点
晚安玛卡巴卡
快乐暑假