浅谈分布式一致性协议

127 阅读5分钟

一、 分布式系统

  1. 分布式系统面临的挑战
  • 数据规模越来越大
  • 服务的可用性要求越来越高
  • 快速迭代的业务要求系统足够易用
  1. 理想中的分布式系统
  • 高性能:可拓展、低时延、高吞吐
  • 正确:一致性、易于理解
  • 可靠:容错、高可用
  1. 从 HDFS 开始

  1. 案例- KV
  • 从最简单机KV开始

  • 接口:

    • Get(key) -> value
    • BatchPut([k1,k2,...],[v1,v2,..])
  • 第一次实现

    • RPC
    • DB Engine

小结

  • 背景:数据规模的不断增加,我们需要大规模分布式系统
  • 维度:对于一个分布式系统,希望能有哪些特征
  • 从KV入手,看看我们如何满足分布式系统的要求

二、 一致性与共识算法

  1. 从复制开始
  • 既然一台机器会挂

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

  1. 如何复制
  • 主副本定期拷贝全量数据到从副本
  • 主副本拷贝操作到从副本

  1. 如何复制操作
  • 主副本把所有的操作打包成 Log

    • 所有的Log 写入都是持久化的,保存在磁盘上
  • 应用包装成状态机,只接收Log 作为Input

  • 主副本确认Log 已经成功写入到副本机器上,当状态机 apply后,返回客户端

  1. 关于读操作
  • 读操作

    • 方案一:直接读状态机,要求写操作进入状态机后再返回client
    • 方案二:写操作复制完成后直接返回,读操作Block 等待所有pending log进入状态机
  • 如果不遵循上述两周方案呢?

    • 可能存在刚刚写入的值读不到的情况(在Log中)

  1. 什么是一致性
  • 对于我们的KV

    • 像操作一台机器一样

      • 要读到最近写入的值
  • 一致性是─种模型(或语义)

    • 来约定一个分布式系统如何向外界(应用)提供服务

    • KV中常见的一致性模型

      • 最终一致性:读取可能暂时读不到但是总会读到
      • 线性一致性:最严格,线性执行
  1. 复制协议-当失效发生
  • 当主副本失效

    • 手动切换。容错?

      • 不,我们的服务还是停了
    • 高可用?

      • 也许,取决于我们从发现到切换的过程的有多快
    • 正确?

      • 操作只从一台机器上发起
      • 所有操作返回前都已经复制到另一台机器了
  1. 共识算法
  • 什么是共识算法?简而言之一个值一旦确定,所有人都认同。

  • 共识协议不等于一致性

    • 应用层面不同的一致性,都可以用共识协议来实现

      • 比如可以故意返回旧的值
    • 简单的复制协议也可以提供线性─致性

  • 一般讨论共识协议时提到的一致性,都指线性一致性

    • 因为弱─致性往往可以使用相对简单的复制算法实现

三、 从Raft 入手

  1. Paxos

The Part-Time Parliamen by Lamport 1989

  • 也就是人们提到的 Paxos
  • 基本上就是一致性协议的的同义词
  • 该算法的正确性是经过证明的
  1. Raft
  • 2014年发表

  • 易于理解作为算法的设计目标

    • 使用了RSM、Log、RPC的概念
    • 直接使用RPC对算法进行了描述
    • Strong Leader-based
    • 使用了随机的方法减少约束
  • 正确性

    • 形式化验证
    • 拥有大量成熟系统
  1. 复制状态机(RSM)
  • RSM (replicated state machine)

    • Raft中所有的consensus都是直接使用Log作为载体
  • Commited Index

    • 一旦Raft更新Commited Index,意味着这个Index前的所有Log都可以提交给状态机了
    • Commited lndex是不持久化的,状态机也是volatile的,重启后从第一条Log开始
  1. Raft 角色

  1. Raft日志复制

箭头是 commit index

  1. Raft从节点失效

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

  1. Raft主节点失效
  • Leader定期的发送AppendEntries RPCs 给其余所有节点

  • 如果Follower有一段时间没有收到Leader的 AppendEntries,则转换身份成为Candidate

  • Candidate自增自己的term,同时使用RequestVote RPCs向剩余节点请求投票

    • raft在检查是否可以投票时,会检查 log是否outdated,至少不比本身旧才会投给对应的Candidate
  • 如果多数派节点投给它,则成为该term的leader

  1. Raft Leader failure

  1. Raft安全性-同Term
  • 对于Term内的安全性

    • 目标:

      • 对于所有已经的commited 的<term, index>位置上至多只有一条 log
  • 由于Raft的多数派选举,我们可以保证在一个term中只有一个leader

    • 我们可以证明一条更严格的声明:在任何<term,index>位置上,至多只有一条log
  1. Raft安全性–跨Term
  • 对于跨Term的安全性

    • 目标:

      • 如果一个 log 被标记commited,那这个log一定会在未来所有的leader中出现Leader completeness
  • 可以证明这个property

    • Raft选举时会检查Log 的是否outdated,只有最新的才能当选Leader
    • 选举需要多数派投票,而commited log 也已经在多数派中(必有overlap)
    • 新Leader一定持有commited log,且 Leader永远不会overwrite log

四、 实现细节以及未来

  1. 案例-KV
  • 多个副本只有单个副本可以提供服务

    • 服务无法水平拓展
  • 增加更多Raft组

    • 如果操作跨Raft 组

  1. 回到共识算法
  • 多节点提交(Leaderless)

    • 节点跨地域,导致节点间的RTT(Round Trip Time)很大

    • EPaxos

      • 使用了冲突图的方式来允许并行Commit
      • 不冲突的情况下1RTT提交时间

  1. 共识算法的未来
  • Raft Paxos相互移植

    • Raft有很多成熟的实现
    • 研究主要关注在Paxos 上
    • 如何关联两种算法

  • 共识算法作为一个系统

    • 多数分布式系统都选择共识算法作为底座·不同一致性协议有不同的特性

    • Virtual consensus in delos

      • 对外暴露─致性的LOG作为借口·内部对于LOG可以选择不同的实现