浅谈分布式一致性协议|青训营笔记

91 阅读5分钟

这是我参与【第四届青训营】笔记创作活动的第4天。

01 分布式系统

1.1 分布式系统面临的挑战

  • 数据规模越来越大
  • 服务的可用性要求越来越高
  • 快速迭代的业务要求系统足够易用

1.2 理想中的分布式系统

  • 高性能:可拓展、低时延、高吞吐
  • 正确:一致性、易于理解
  • 可靠:容错、高可用

1.3 从HDFS开始

image.png

02 一致性与共识算法

2.1 从复制开始

既然一台机器会挂

image.png

如果两个副本都能接受请求

image.png

2.2 复制方式

  • 主副本定期拷贝全量数据到从副本
  • 主副本拷贝操作到从副本

image.png

2.3 如何复制操作

  • 主副本把所有的操作打包成 Log
    • 所有的Log 写入都是持久化的,保存在磁盘上
  • 应用包装成状态机,只接收Log作为Input
  • 主副本确认Log 已经成功写入到副本机器上,当状态机 apply后,返回客户端

image.png

2.4 关于读操作

  • 读操作
    • 方案一:直接读状态机,要求写操作进入状态机后再返回client
    • 方案二:写操作复制完成后直接返回,读操作 Block等待所有pending log进入状态机
  • 如果不遵循上述两周方案呢?
    • 可能存在刚刚写入的值读不到的情况(在Log中)

2.5 什么是一致性

  • 对于我们的KV
    • 像操作一台机器一样
    • 要读到最近写入的值
  • 一致性是一种模型(或语义)
    • 来约定一个分布式系统如何向外界(应用)提供服务. KV中常见的一致性模型
    • 最终—致性:读取可能暂时读不到但是总会读到·线性一致性:最严格,线性执行

image.png

2.6 复制协议

  • 当主副本失效时,为了使得算法简单
    • 我们人肉切换,只要足够快
      • 我们还是可以保证较高的可用性。
  • 但是如何保证主副本是真的失效了听呢?
    • 在切换的过程中,主副本又开始接收client端的请求
    • 两个主副本显然是不正确的,log会被覆盖写掉
    • 我们希望算法能在这种场景下仍然保持正确
  • 要是增加到三个节点呢?
    • 每次都等其他节点操落盘性能较差
    • 能下能允许少数节点挂了的情况下,仍然可以工作
      • falut-tolerance

2.7 共识算法

共识算法:简而言之一个值一旦确定,所有人都认同。

  • 共识协议不等于—致性
    • 应用层面不同的一致性,都可以用共识协议来实现
      • 比如可以故意返回日的值
    • 简单的复制协议也可以提供线性—致性
  • 一般讨论共识协议时提到的一致性,都指线性—致性
    • 因为弱—致性往往可以使用相对简单的复制算法实现

03 从Raft入手

3.1 Paxons

The Part-Time Parliamen by Lamport 1989

  • 也就是人们提到的Paxos
  • 基本上就是—致性协议的的同义词
  • 该算法的正确性是经过证明的

3.2 Raft

  • 2014年发表
  • 易于理解作为算法的设计目标
    • 使用了RSM、Log、RPC的概念
    • 直接使用RPC对算法进行了描述
    • Strong Leader-based
    • 使用了附随机的方法减少约束
  • 正确性
    • 形式化验证
    • 拥有大量成熟系统

image.png

3.3 复制状态机(RSM)

  • RSM (replicated state machine)
    • Raft 中所有的consensus都是直接使用Log 作为载体
  • Commited Index
    • 一旦Raft更新Commited Index,意味着这个Index前的所有Log都可以提交给状态机了
    • Commited Index是不持久化的,状态机也是volatile的,重启后从第一条Log 开始

image.png

3.4 Raft角色

image.png

3.5 Raft整体流程

image.png

3.6 Raft日志复制

image.png

3.7 Raft从节点失效

image.png

3.8 Raft Term

  • 每个Leader服务于一个term
  • 每个term至多只有一个leader
  • 每个节点存储当前的term
  • 每个节点term从一开始,只增不减
  • 所有rpc的request reponse都携带term
  • 只commit 本term 内的log

image.png

3.9 Raft主节点失效

  • Leader定期的发送AppendEntries RPCs 给其余所有节点
  • 如果Follower有一段时间没有收到Leader 的AppendEntries,则转换身份成为Candidate
  • Candidate自增自己的term,同时使用RequestVote RPCs向剩余节点请求投票
    • raft在检查是否可以投票时,会检查log是否outdated,至少不比本身旧才会投给对应的Candidate
  • 如果多数派节点投给它,则成为该term的leader

3.10 Raft Leader failure

image.png

3.11 Raft安全性

同Term

  • 对于Term内的安全性
    • 目标:对于所有已经的commited的<term, index>位置上至多只有一条log
  • 由于Raft的多数派选举,我们可以保证在一个term中只有一个leader
    • 我们可以证明一条更严格的声明:在任何<term,index>位置上,至多只有一条log

跨Term

  • 对于跨Term的安全性
    • 目标:如果一个log被标记commited,那这个log一定会在未来所有的leader中出现Leader completeness
  • 可以证明这个property
    • Raft选举时会检查Log 的是否outdated,只有最新的才能当选 Leader
    • 选举需要多数派投票,而commited log 也已经在多数派中(必有overlap)
    • 新Leader一定持有commited log,且Leader永远不会overwrite log

安全性验证

  • Raft使用TLA+进行了验证
    • 形式验证(Formal Method)以数学的形式对算法进行表达,由计算机程序对算法所有的状态进行遍历

参考文章

分布式一致性算法-Paxos、Raft、ZAB、Gossip - 知乎 (zhihu.com)