分布式系统原理

Quorum 机制

Quorum 机制是一种简单有效的副本管理机制。本节首先讨论一种最简单的副本控制规则write-all-read-one,在此基础上,放松约束,讨论 quorum 机制。

1. 约定

为了简化讨论,本节先做这样的约定:更新操作(write)是一系列顺序的过程,通过其他机制确定更新操作的顺序(例如 primary-secondary 架构中由 primary 决定顺序),每个更新操作记为 w i ,i 为更新操作单调递增的序号,每个 w i 执行成功后副本数据都发生变化,称为不同的数据版本,记作 v i 。假设每个副本都保存了历史上所有版本的数据。

2. Write-all-read-one

Write-all-read-one(简称 WARO)是一种最简单的副本控制规则,顾名思义即在更新时写所有的副本,只有在所有的副本上更新成功,才认为更新成功,从而保证所有的副本一致,这样在读取数据时可以读任一副本上的数据。

  • 假设有一种 magic 的机制,当某次更新操作 w i 一旦在所有 N 个副本上都成功,此时全局都能知道这个信息,此后读取操作将指定读取数据版本为 v i 的数据,称在所有 N 个副本上都成功的更新操作为“成功提交的更新操作”,称对应的数据为“成功提交的数据”。在 WARO 中,如果某次更新操作 w i 在某个副本上失败,此时该副本的最新的数据只有 v i-1 ,由于不满足在所有 N 个副本上都成功,则 w i 不是一个“成功提交的更新操作”,此时,虽然其他 N-1 个副本上最新的数据是 v i ,但 v i 不是一个“成功提交的数据”,最新的成功提交的数据只是 v i-1 。

  • 分析一下 WARO 的可用性。由于更新操作需要在所有的 N 个副本上都成功,更新操作才能成功,所以一旦有一个副本异常,更新操作失败,更新服务不可用。对于更新服务,虽然有 N 个副本,但系统无法容忍任何一个副本异常。另一方面,N 个副本中只要有一个副本正常,系统就可以提供读服务。对于读服务而言,当有 N 个副本时,系统可以容忍 N-1 个副本异常。

  • 从上述分析可以发现 WARO 读服务的可用性较高,但更新服务的可用性不高,甚至虽然使用了副本,但更新服务的可用性等效于没有副本。

  • WARO 牺牲了更新服务的可用性,最大程度的增强读服务的可用性。

3. Quorum 定义

在 Quorum 机制下,当某次更新操作 w i 一旦在所有 N 个副本中的 W 个副本上都成功,则就称该更新操作为“成功提交的更新操作”,称对应的数据为“成功提交的数据”。令 R>N-W,由于更新操作 w i 仅在 W 个副本上成功,所以在读取数据时,最多需要读取 R 个副本则一定能读到 w i 更新后的数据 v i 。如果某次更新 w i 在 W 个副本上成功,由于 W+R>N,任意 R 个副本组成的集合一定与成功的 W 个副本组成的集合有交集,所以读取 R 个副本一定能读到 w i 更新后的数据 v i 。

例 2.4.1,某系统有 5 个副本,W=3,R=3,最初 5 个副本的数据一致,都是 v 1 , 某次更新操作w 2 在前 3 副本上成功,副本情况变成(v 2 v 2 v 2 v 1 v 1 )。此时,任意 3 个副本组成的集合中一定包括v 2 。

在上述定义中,令 W=N,R=1,就得到 WARO,即 WARO 是 Quorum 机制的一种特例。

与分析 WARO 相似,分析 Quorum 机制的可用性。限制 Quorum 参数为 W+R=N+1。由于更新操作需要在 W 个副本上都成功,更新操作才能成功,所以一旦 N-W+1 个副本异常,更新操作始终无法在 W 个副本上成功,更新服务不可用。另一方面,一旦 N-R+1 个副本异常,则无法保证一定可以读到与 W 个副本有交集的副本集合,则读服务的一致性下降。

Quorum 机制的三个系统参数 N、W、R 控制了系统的可用性,也是系统对用户的服务承诺:数据最多有 N 个副本,但数据更新成功 W 个副本即返回用户成功。

4. 读取最新成功提交的数据

上节中,假设有某种 magic 的机制使得读取者知道当前已提交的数据版本号。本节取消这种假设,分析在 Quorum 机制下,如何始终读取成功提交的数据,以及如何确定最新的已提交的数据。

Quorum 机制只需成功更新 N 个副本中的 W 个,在读取 R 个副本时,一定可以读到最新的成功提交的数据。但由于有不成功的更新情况存在,仅仅读取 R 个副本却不一定能确定哪个版本的数据是最新的已提交的数据
例 2.4.3,在 N=5,W=3,R=3 的系统中,某时刻副本最大版本号为 ( v 2 v 2 v 2 v 1 v 1 )。注意,这里继续假设有 v 2 的副本也有 v 1 ,上述列出的只是最大版本号。此时,最新的成功提交的副本应该是 v 2 ,因为从全局看 v 2 已经成功更新了 3 个副本。读取任何 3 个副本,一定能读到 v 2 。 但仅读 3 个副本时,有可能读到 ( v 2 v 1 v 1 ),如图 2-11(a)。此时,由于 v 2 蕴含 v 1 , 可知 v 1 是一个成功提交的版本 , 但却不能判定 v 2 一定是一个成功提交的版本 。 这是因为,图 2-11(b),假设副本最大版本号为 ( v 2 v 1 v 1 v 1 v 1 ),当读取 3 个副本时也可能读到 ( v 2 v 1 v 1 ),此时 v 2 是一个未成功提交的版本。所以在本例中,仅仅读到 ( v 2 v 1 v 1 )时,可以肯定的是最新的成功提交的数据要么是 v 1 要么是 v 2 ,却没办法确定究竟是哪一个 。

对于一个强一致性系统,应该始终读取返回最新的成功提交的数据,在 quorum 机制下,要达到这一目的需要对读取条件做进一步加强。

1. 限制提交的更新操作必须严格递增,即只有在前一个更新操作成功提交后才可以提交后一个更新操作,从而成功提交的数据版本号必须是连续增加的。
2. 读取 R 个副本,对于 R 个副本中版本号最高的数据,
    2.1 若已存在 W 个,则该数据为最新的成功提交的数据
    2.2 若存在个数据少于 W 个,假设为 X 个,则继续读取其他副本,直若成功读取到 W 个该版本的副本,则该数据为最新的成功提交的数据;如果在所有副本中该数据的个数肯定不满足 W 个,则 R 中版本号第二大的为最新的成功提交的副本。

例 2.4.4:依旧接例 2.4.3,在读取到 ( v 2 v 1 v 1 )时,继续读取剩余的副本,若读到剩余两个副本为(v 2 v 2 )则 v 2 是最新的已提交的副本;若读到剩余的两个副本为(v 2 v 1 )或(v 1 v 1 )则 v 1 是最新成功提交的版本;若读取后续两个副本有任一超时或失败,则无法判断哪个版本是最新的成功提交的版本。

可以看出,在单纯使用 Quorum 机制时,若要确定最新的成功提交的版本,最多需要读取 R+(W-R-1)=N 个副本,当出现任一副本异常时,读最新的成功提交的版本这一功能都有可能不可用。实际工程中,应该尽量通过其他技术手段,回避通过 Quorum 机制读取最新的成功提交的版本。例如,当 quorum 机制与 primary-secondary 控制协议结合使用时,可以通过读取 primary 的方式读取到最新的已提交的数据。

5. 基于 Quorum 机制选择 primary

本节介绍一种介于 quorum 机制选择 primary 的技术。回忆 2.2.2 节,基本 primary-secondary 协议中,primary 负责进行更新操作的同步工作。现在基本 primary-secondary 协议中引入 quorum 机制,即 primary 成功更新 W 个副本(含 primary 本身)后向用户返回成功。

在 primary-secondary 协议中,当 primary 异常时,需要选择出一个新的 primary,之后 secondary 副本与 primary 同步数据。通常情况下,选择新的 primary 的工作是由某一中心节点完成的,在引入 quorum 机制后,常用的 primary 选择方式与读取数据的方式类似,即中心节点读取 R 个副本,选择 R 个副本中版本号最高的副本作为新的 primary。新 primary 与至少 W 个副本完成数据同步后作为新 的 primary 提供读写服务。首先,R 个副本中版本号最高的副本一定蕴含了最新的成功提交的数据。 再者,虽然不能确定最高版本号的数是一个成功提交的数据,但新的 primary 在随后与 secondary 同步数据,使得该版本的副本个数达到 W,从而使得该版本的数据成为成功提交的数据。

例 2.4.5:在 N=5,W=3,R=3 的系统中,某时刻副本最大版本号为 ( v 2 v 2 v 1 v 1 v 1 ),此时 v 1 是系统的最新的成功提交的数据 , v 2 是一个处于中间状态的未成功提交的数据。假设此刻原 primary副本异常,中心节点进行 primary 切换工作。这类“中间态”数据究竟作为“脏数据”被删除,还是作为新的数据被同步后成为生效的数据,完全取决于这个数据能否参与新 primary 的选举。下面分别分析这两种情况。

  • 第一、如图 2-12,若中心节点与其中 3 个副本通信成功,读取到的版本号为(v 1 v 1 v 1 ),则任选一个副本作为primary,新primary以v 1 作为最新的成功提交的版本并与其他副本同步,当与第1、第 2 个副本同步数据时,由于第 1、第 2 个副本版本号大于 primary,属于脏数据,可以按照 2.2.2.4节中介绍的处理脏数据的方式解决。实践中,新 primary 也有可能与后两个副本完成同步后就提供数据服务,随后自身版本号也更新到 v 2 , 如果系统不能保证之后的 v 2 与之前的 v 2 完全一样,则新primary 在与第 1、2 个副本同步数据时不但要比较数据版本号还需要比较更新操作的具体内容是否一样。

第二、若中心节点与其他 3 个副本通信成功,读取到的版本号为(v 2 v 1 v 1 ),则选取版本号为v2 的副本作为新的 primary,之后,一旦新 primary 与其他 2 个副本完成数据同步,则符合 v 2 的副本个数达到 W 个,成为最新的成功提交的副本,新 primary 可以提供正常的读写服务。

6. 工程投影

  • GFS 中的 Quorum。GFS 使用 WARO 机制读写副本。GFS 系统不保证异常状态时副本的一致性,GFS 系统需要上层应用通过 Checksum 等机制自行判断数据是否合法。

  • Dynamo 中的 Quorum。Dynamo/Cassandra 是一种去中心化的分布式存储系统。Dynamo 使用 Quorum 机制来管理副本。用户可以配置 N、R、W 的参数,并保证满足 R+W>N 的 quorum 要求。Dynamo 提出了一种 clock vector 的方法,该方法的思路就是记录数据的版本变化,以类似 MVCC(2.7 )的方式帮助用户解决数据冲突。所谓 clock vector即记录了数据变化的路径的向量,为每个更新操作维护分配一个向量元素,记录数据的版本号及主导该次更新的副本名字。

  • Zookeeper 中的 Quorum。Zookeeper 使用的 paxos 协议本身就是利用了 Quorum机制,在 2.8 中有详细分析,这里不赘述。当利用 paxos 协议外选出 primary 后,Zookeeper 的更新流量由 primary 节点控制,每次更新操作,primary 节点只需更新超过半数(含自身)的节点后就返回用户成功。每次更新操作都会递增各个节点的版本号(xzid)。当 primary 节点异常,利用 paxos 协议选举新的 primary 时,每个节点都会以自己的版本号发起 paxos 提议,从而保证了选出的新 primary 是某个超过半数副本集合中版本号最大的副本。

  • Mola*/Armor*中的 Quorum。Mola*和 Armor*系统中所有的副本管理都是基于 Quorum,即数据在多数副本上更新成功则认为成功。

  • Big Pipe*中的 Quorum。Big Pipe*中的副本管理也是采用了 WARO 机制。

参考:《分布式系统原理介绍》 - 刘杰

分布式系统原理 之4 Quorum 机制相关推荐

  1. 分布式系统原理 之3 Lease机制

    分布式系统原理 Lease机制 Lease 机制是最重要的分布式协议,广泛应用于各种实际的分布式系统中.即使在某些系统中相似的设计不被称为 lease,但我们可以分析发现其本质就是一种 lease 的 ...

  2. leetcode每日一题--雀巢原理;抽屉算法;Quorum机制;分布式应用

    leetcode每日一题 539. 最小时间差 示例 1: 输入:timePoints = ["23:59","00:00"] 输出:1 示例 2: 输入:ti ...

  3. 分布式系统Quorum机制

    Write-all-read-one Write-all-read-one(简称 WARO)是一种最简单的副本控制规则,顾名思义即在更新时写所有的副本,只有在所有的副本上更新成功,才认为更新成功,从而 ...

  4. 深度介绍分布式系统原理与设计

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 1 概念 1.1 模型 1.2 副本 1.3 衡量分布式系 ...

  5. 两万字深度介绍分布式系统原理,一文入魂

    1 概念 1.1 模型 节点 在具体的工程项目中,一个节点往往是一个操作系统上的进程.在本文的模型中,认为节点是一个完整的.不可分的整体,如果某个程序进程实际上由若干相对独立部分构成,则在模型中可以将 ...

  6. 分布式系统原理 之9 CAP 理论

    分布式系统原理 CAP 理论 CAP 理论是由 Eric Brewer 提出的分布式系统中最为重要的理论之一[8].本文将 CAP 理论安排在原理部分的最后介绍是为了利用前面已经介绍过的几种分布式协议 ...

  7. 分布式系统原理 之2 基本副本协议

    分布式系统原理 基本副本协议 副本控制协议指按特定的协议流程控制副本数据的读写行为,使得副本满足一定的可用性和一致性要求的分布式协议. 副本控制协议要具有一定的对抗异常状态的容错能力,从而使得系统具有 ...

  8. 两万字深度介绍分布式系统原理!【收藏版】

    1 概念 1.1 模型 1.2 副本 1.3 衡量分布式系统的指标 2 分布式系统原理 2.1 数据分布方式 2.2 基本副本协议 2.3 Lease 机制 2.4 Quorum 机制 2.5 日志技 ...

  9. 两万字深度介绍分布式系统原理,一篇通透

    转自:Guanzhou Song 1 概念 1.1 模型 节点 在具体的工程项目中,一个节点往往是一个操作系统上的进程.在本文的模型中,认为节点是一个完整的.不可分的整体,如果某个程序进程实际上由若干 ...

最新文章

  1. lua元表和元方法 《lua程序设计》 13章 读书笔记
  2. Gym 101334F Feel Good
  3. java neo4j_java连接neo4j
  4. UTF-8编码规则(转)
  5. 【网络编程】用Socket实现聊天小程序
  6. Node — 第二天
  7. 一文教你使用java开发一款推箱子游戏
  8. Apple`s Steve Jobs Has Reshaped(重塑) the Tech World: 10 Ways He Did It
  9. 关于Google Storage的东西
  10. 谁说国产编译器没救了?这个 C/C++ 和 JavaScript 编译器来了 | 程序人生 2020
  11. 运行中的linux备份系统盘,怎样使用ghost对linux进行系统备份?
  12. C语言实现文件复制 fgetc、fputc函数的使用 带详细注释版
  13. 增强型绿植植被指数_辽宁省增强型植被指数EVI
  14. 重读《从菜鸟到测试架构师》-- 从专家到高手
  15. 郦旭东小可爱的大数据算法课程期末复习
  16. Caused by: java.lang.IllegalStateException: Failed to introspect Class
  17. 野派,阡陌人生路,泪断愁肠,滚滚红尘中,情留心房
  18. 影评系统的机遇和挑战
  19. 界面专访丁珂:多数企业安全体系落后,上云是最快速解法
  20. veket linux输入法,智能通用输入法平台(SCIM for veket)

热门文章

  1. 机器学习-降维之主成分分析PCA算法原理及实战
  2. 数据挖掘竞赛-轴承故障检测训练赛
  3. clob类型用java怎么存,Java 储存和读取 oracle CLOB 类型字段的实用方法
  4. CreatePipe匿名管道通信
  5. 2_6 CompositeMode.cpp 组合模式
  6. Linux网络编程 | Socket编程(二)TCPSocket的封装、TCP服务器多进程、多线程版本的实现
  7. 80%的Linux都不懂的内存问题
  8. 面试官灵魂拷问:为什么 SQL 语句不要过多的 join?
  9. 图文:关于进程与线程,我看过最通俗的解释!
  10. ElasticSearch 性能优化实战,让你的 ES 飞起来!