zoukankan      html  css  js  c++  java
  • 分布式系统理论之Quorum机制

    转载:https://www.cnblogs.com/hapjin/p/5626889.html

    https://www.iteye.com/news/32340

    Quorum

    一,Quorum机制介绍

    在分布式系统中有个CAP理论,对于P(分区容忍性)而言,是实际存在 从而无法避免的。因为,分布系统中的处理不是在本机,而是网络中的许多机器相互通信,故网络分区、网络通信故障问题无法避免。因此,只能尽量地在C 和 A 之间寻求平衡。对于数据存储而言,为了提高可用性(Availability),采用了副本备份,比如对于HDFS,默认每块数据存三份。某数据块所在的机器宕机了,就去该数据块副本所在的机器上读取(从这可以看出,数据分布方式是按“数据块”为单位分布的)

    但是,问题来了,当需要修改数据时,就需要更新所有的副本数据,这样才能保证数据的一致性(Consistency)。因此,就需要在 C(Consistency) 和 A(Availability) 之间权衡。

    而Quorum机制,就是这样的一种权衡机制,一种将“读写转化”的模型。在介绍Quorum之前,先看一个极端的情况:WARO机制

     WARO(Write All Read one)是一种简单的副本控制协议,当Client请求向某副本写数据时(更新数据),只有当所有的副本都更新成功之后,这次写操作才算成功,否则视为失败。

    从这里可以看出两点:①写操作很脆弱,因为只要有一个副本更新失败,此次写操作就视为失败了。②读操作很简单,因为,所有的副本更新成功,才视为更新成功,从而保证所有的副本一致。这样,只需要读任何一个副本上的数据即可。假设有N个副本,N-1个都宕机了,剩下的那个副本仍能提供读服务;但是只要有一个副本宕机了,写服务就不会成功。

     WARO牺牲了更新服务的可用性,最大程度地增强了读服务的可用性。而Quorum就是更新服务和读服务之间进行一个折衷。

    Quorum机制是“抽屉原理”的一个应用。定义如下:假设有N个副本,更新操作wi 在W个副本中更新成功之后,才认为此次更新操作wi 成功。称成功提交的更新操作对应的数据为:“成功提交的数据”。对于读操作而言,至少需要读R个副本才能读到此次更新的数据。其中,W+R>N ,即W和R有重叠。一般,W+R=N+1

    假设系统中有5个副本,W=3,R=3。初始时数据为(V1,V1,V1,V1,V1)--成功提交的版本号为1

    当某次更新操作在3个副本上成功后,就认为此次更新操作成功。数据变成:(V2,V2,V2,V1,V1)--成功提交后,版本号变成2

    因此,最多只需要读3个副本,一定能够读到V2(此次更新成功的数据)。而在后台,可对剩余的V1 同步到V2,而不需要让Client知道。

    二,Quorum机制分析

    ①Quorum机制无法保证强一致性

    所谓强一致性就是:任何时刻任何用户或节点都可以读到最近一次成功提交的副本数据。强一致性是程度最高的一致性要求,也是实践中最难以实现的一致性。

     因为,仅仅通过Quorum机制无法确定最新已经成功提交的版本号。

    比如,上面的V2 成功提交后(已经写入W=3份),尽管读取3个副本时一定能读到V2,如果刚好读到的是(V2,V2,V2),则此次读取的数据是最新成功提交的数据,因为W=3,而此时刚好读到了3份V2。如果读到的是(V2,V1,V1),则无法确定是一个成功提交的版本,还需要继续再读,直到读到V2的达到3份为止,这时才能确定V2 就是已经成功提交的最新的数据。

    1)如何读取最新的数据?---在已经知道最近成功提交的数据版本号的前提下,最多读R个副本就可以读到最新的数据了。

    2)如何确定 最高版本号 的数据是一个成功提交的数据?---继续读其他的副本,直到读到的 最高版本号副本 出现了W次。

    ②基于Quorum机制选择 primary

    中心节点(服务器)读取R个副本,选择R个副本中版本号最高的副本作为新的primary

    新选出的primary不能立即提供服务,还需要与至少与W个副本完成同步后,才能提供服务---为了保证Quorum机制的规则:W+R>N

    至于如何处理同步过程中冲突的数据,则需要视情况而定。

     比如,(V2,V2,V1,V1,V1),R=3,如果读取的3个副本是:(V1,V1,V1)则高版本的 V2需要丢弃。

    如果读取的3个副本是(V2,V1,V1),则低版本的V1需要同步到V2

    三、微信的实践

    Quorum借鉴了Paxos的思想,实现上更加简洁,同样解决了在多个节点并发写入时的数据一致性问题。比如Amazon的Dynamo云存储系统中,就应用NWR来控制一致性。微信也有大量分布式存储使用这个协议保证一致性。Quorum最初的思路来自“鸽巢原理”,同一份数据虽然在多个节点拥有多份副本,但是同一时刻这些副本只能用于读或者只能用于写。 

    图3 Quorum模型:微信改进的版本、数据分离结构
    • Quorum控制同一份数据不会同时读写,写请求需要的副本数要求超过半数,写操作时就没有足够的副本给读操作;
    • Quorum控制同一份数据的串行化修改,因为副本数要求,同一份数据不会被两个写请求同时修改。

    Quorum又被称为NWR协议:R表示读取副本的数量;W表示写入副本的数量;N表示总的节点数量。 

    • 假设N=2,R=1,W=1,R+W=N=2,在节点1写入,节点2读取,无法得到一致性的数据;
    • 假设N=2,R=2,W=1,R+W>N,任意写入某个节点,则必须同时读取所有节点;
    • 假设N=2,W=2,R=1,R+W>N,同时写入所有节点,则读取任意节点就可以得到结果。

    要满足一致性,必须满足R+W>N。NWR值的不同组合有不同效果,当W+R>N时能实现强一致性。所以工程实现上需要N>=3,因为冗余数据是保证可靠性的手段,如果N=2,损失一个节点就退化为单节点。写操作必须更新所有副本数据才能操作完成,对于写频繁的系统,少数节点被写入的数据副本可以异步同步,但是只更新部分节点,读取则需要访问多个节点,读写总和超过总节点数才能保证读到最新数据。可以根据请求类型调整BWR,需要可靠性则加大NR,需要平衡读写性能则调整RW。 

    微信有大量分布式存储(QuorumKV)使用这个算法保证一致性,我们对这个算法做了改进,创造性地把数据副本分离出版本编号和数据存到不同设备,其中N=3(数据只有2份,版本编号有3份),在R=W=2时仍然可以保证强一致性。因为版本编号存放3份,对版本编号使用Quorum方式,通过版本编号协商,只有版本序号达成一致的情况下读写单机数据,从而在保证强一致性的同时实现高读写性能。实际数据只写入一台数据节点,使用流水日志的方式进行同步,并更新版本编号。但是我们的分布式存储(QuorumKV)仍存在数据可靠性比Paxos低的问题,因为数据只写一份副本,依靠异步同步。如果数据节点故障,故障节点上没有同步到另一个节点,数据将无法访问。版本节点故障时,如果Quorum协议没有设置W=3,也可能无法访问正确的数据节点副本。 

    对于分布式存储:

    分布式存储选用不同的一致性算法,和业务的具体情况相关。我们的分布式存储在发展的不同阶段,使用过不同的算法:业务的发展初期使用Quorum算法,成本压力减少而业务稳定需求变大后,就开始使用Paxos算法。如果业务模型对数据一致性要求不高,使用Quorum则具有一定的成本和开发资源优势。 

  • 相关阅读:
    BZOJ 3744 Gty的妹子序列
    BZOJ 3872 Ant colony
    BZOJ 1087 互不侵犯
    BZOJ 1070 修车
    BZOJ 2654 tree
    BZOJ 3243 向量内积
    1003 NOIP 模拟赛Day2 城市建设
    CF865D Buy Low Sell High
    CF444A DZY Loves Physics
    Luogu 4310 绝世好题
  • 原文地址:https://www.cnblogs.com/fanguangdexiaoyuer/p/10278107.html
Copyright © 2011-2022 走看看