• Feeds

  • Posts Tagged ‘paxos’


    多IDC的数据分布设计(二)

    在前文《多IDC的数据分布设计(一)》中介绍了多IDC数据一致性的几种实现原理,遗憾的是,目前虽然有不少分布式产品,但几乎都没有开源的产品专门针对IDC来优化。本文从实践的角度分析各种方法优缺点。

    背景资料 Latency差异

    Jeff Dean提到不同数据访问方式latency差异

    Numbers Everyone Should Know
    L1 cache reference                           0.5 ns
    Branch mispredict                            5 ns
    L2 cache reference                           7 ns
    Mutex lock/unlock                           25 ns
    Main memory reference                      100 ns
    Compress 1K bytes with Zippy             3,000 ns
    Send 2K bytes over 1 Gbps network       20,000 ns
    Read 1 MB sequentially from memory     250,000 ns
    Round trip within same datacenter      500,000 ns
    Disk seek                           10,000,000 ns
    Read 1 MB sequentially from disk    20,000,000 ns
    Send packet CA->Netherlands->CA    150,000,000 ns

    这个数据对于我们设计多IDC数据访问策略具有关键的指导作用,我们可以用这个数据来衡量数据架构来如何设计才能满足高并发低延迟的目标。
    这份数据实际上对所有网络应用及分布式应用开发者都具有很大借鉴作用,数据需要根据访问频率尽量放在latency小的地方

    1. 2PC/3PC/Paxos模式

    在上文中提到,2PC/3PC相比Paxos有明显的缺点,因此最好不用于生产环境,这里就不再详述。
    Paxos选择了CAP理论中的”Consistency, Partition”, 需要牺牲availability。它可以在多个IDC之间实现强一致性复制。

    Paxos缺点

    • IDC之间需要高速稳定网络
    • 一个2f+1个节点的网络中,需要f+1个节点完成事务才能成功。
    • Throughput低,不适合高请求量的场合。所以大部分分布式存储产品并不直接使用Paxos算法来同步数据。

    2. Dynamo模式

    Dynamo论文中并未专门描述Dynamo算法是否适合多IDC场景,只有少量文字提到

    In essence, the preference list of a key is constructed such that the storage nodes are spread across multiple data centers. These datacenters are connected through high speed network links. This scheme of replicating across multiple datacenters allows us to handle entire data center failures without a data outage.

    从上文看到,前提条件是“high speed network links” 可能对国内的情况不太适用。假如IDC之间网络不稳定,那会发生哪些情况呢?

    Quorum 算法中,如果要考虑高可用性,则数据需要分布在多个机房。双机房如NRW=322由于单机房故障后可能会发生3个点中2个点都在故障机房,导致出现数据不 可用的情况,所以合适的部署是NRW=533,需要3个机房。大部分请求需要2个机房节点返回才能成功,考虑到多IDC的带宽及latency,性能自然会很差。

    Quorum算法在读写的时候都要从quorum中选取一个coordinator,算法如下

    A node handling a read or write operation is known as the
    coordinator. Typically, this is the first among the top N nodes in
    the preference list. If the requests are received through a load
    balancer, requests to access a key may be routed to any random
    node in the ring. In this scenario, the node that receives the
    request will not coordinate it if the node is not in the top N of the
    requested key’s preference list. Instead, that node will forward the
    request to the first among the top N nodes in the preference list.

    如果严格按照Dynamo协议,coodinator一定要在N中第一个节点,那在3个机房中将有2/3的请求需要forward到异地机房的 coordinator执行,导致latency增大。如果对coodinator选择做优化,让client选取preference list中前N个节点中在本地机房的一个节点作为coordinator,这样会一定程度降低latency,但是会存在相同的key选择不同节点作为 coordinator的概率增大,导致数据conflict的概率增大。

    同时在多机房模式下,Failure detection容易产生混乱。Dynamo并没有使用一致性的failure view来判断节点失效。而是由每个节点独自判断。

    Failure detection in Dynamo is used to avoid attempts to
    communicate with unreachable peers during get() and put()
    operations and when transferring partitions and hinted replicas.
    For the purpose of avoiding failed attempts at communication, a
    purely local notion of failure detection is entirely sufficient: node
    A may consider node B failed if node B does not respond to node
    A’s messages (even if B is responsive to node C’s messages).

    而最近非常流行的Cassandra基本上可以看作是开源的Dynamo clone, 它在Facebook Inbox Search项目中部署在150台节点上,并且分布在美国东西海岸的数据中心。

    The system(Facebook Inbox Search) currently stores about 50+TB of data on a 150 node cluster, which is spread out between east and west coast data centers.

    虽然在它的JIRA中有一个提案 CASSANDRA-492 是讲”Data Center Quorum”,但是整体看来Cassandra并没有特别的针对对IDC的优化,它的paper[5]中提到

    Data center failures happen due to power outages, cooling
    failures, network failures, and natural disasters. Cassandra
    is configured such that each row is replicated across multiple
    data centers. In essence, the preference list of a key is con-
    structed such that the storage nodes are spread across mul-
    tiple datacenters. These datacenters are connected through
    high speed network links. This scheme of replicating across
    multiple datacenters allows us to handle entire data center
    failures without any outage.

    跟Dynamo中的描述几乎是相同的。

    3. PNUTS模式

    PNUTS模式是目前最看好的多IDC数据同步方式。它的算法大部分是为多IDC设计。

    PNUTS主要为Web应用设计,而不是离线数据分析(相比于Hadoop/HBase)。

    • Yahoo!的数据基本都是用户相关数据,典型的以用户的username为key的key value数据。
    • 统计数据访问的特征发现85%的用户修改数据经常来源自相同的IDC。

    根据以上的数据特征,Yahoo!的PNUTS实现算法是

    • 记录级别的master, 每一条记录选择一个IDC作为master,所有修改都需要通过master进行。即使同一个表(tablet)中不同的记录master不同。
    • master上的数据通过Yahoo! Message Broker(YMB)异步消息将数据复制到其他IDC。
    • master选择具有灵活的策略,可以根据最新修改的来源动态变更master IDC, 比如一个IDC收到用户修改请求,但是master不在本地需要转发到远程master修改,当远程修改超过3次则将本地的IDC设成master。
    • 每条记录每次修改都有一个版本号(per-record timeline consisitency),master及YMB可以保证复制时候的顺序。

    Yahoo!的PNUTS实际可理解为master-master模式。
    一致性:由于记录都需通过master修改,master再复制到其他IDC, 因此可达到所有IDC数据具有最终一致性。
    可用性

    • 由于所有IDC都有每条记录的本地数据,应用可以根据策略返回本地cache或最新版本。
    • 本地修改只要commit到YMB即可认为修改成功。
    • 任一IDC发生故障不影响访问。

    论文中提到的其他优点

    hosted, notifications, flexible schemas, ordered records, secondary indexes, lowish latency, strong consistency on a single record, scalability, high write rates, reliability, and range queries over a small set of records.

    总之,PNUTS可以很好的适合geographic replication模式。

    • 记录publish到本地YMB则认为成功,免除Dynamo方式需要等待多个Data Center返回的latency。
    • 如果发生master在异地则需要将请求forward到异地,但是由于存在master转移的策略,需要forward的情况比较少。

    极端情况,当record的master不可用时候,实现上似乎有些可疑之处,读者可自行思考。

    Under normal operation, if the master copy of a record fails, our system has protocols to fail over to another replica. However, if there are major outages, e.g. the entire region that had the master copy for a record becomes unreachable, updates cannot continue at another replica without potentially violating record-timeline consistency. We will allow applications to indicate, per-table, whether they want updates to continue in the presence of major outages, potentially branching the record timeline. If so, we will provide automatic conflict resolution and notifications thereof. The application will also be able to choose from several conflict resolution policies: e.g., discarding one branch, or merging updates from branches, etc.

    初步结论

    低带宽网络
    PNUTS record-level mastering模式最佳。
    高带宽低延迟网络
    (1Gbps, Latency < 50ms)
    1. 用Dynamo Quorum, vector clock算法实现最终一致性
    2. 用Paxos实现强一致性

    后记

    本文从开始准备到发布时间较长,由于在多IDC数据访问方面目前业界并无统一的成熟方案,相关资料和文献也相对较少,而且对这方面有兴趣且有相应环境的人不多,短时间要提出自己成熟独立的见解也具有一定难度,本文仅包含一些不成熟的想法的整理,由于自己对文中的观点深度也不是满意,所以一直没有最终完稿发布。但考虑到最近工作较忙,暂时没有精力继续深入研究,所以希望公开文章抛砖引玉,同时也欢迎对这方面课题有兴趣者进一步交流探讨。

    Resource

    1. Ryan Barrett, Transactions Across Datacenters
    2. Jeff Dean, Designs, Lessons and Advice from Building Large Distributed Systems (PDF)
    3. PNUTS: Yahoo!’s Hosted Data Serving Platform (PDF)
    4. Thoughts on Yahoo’s PNUTS distributed database
    5. Cassandra – A Decentralized Structured Storage System (PDF)
    6. Yahoo!的分布式数据平台PNUTS简介及感悟

    多IDC的数据分布设计(一)

    上个月跟某个朋友谈及多IDC数据同时读写访问的问题(tweet),当时觉得有不少解决方案,但觉得思路还不够清晰。最近看了Google App Engine工程师Ryan Barrett介绍GAE后端数据服务的演讲稿Transactions Across Datacenters(视频),用Ryan的方法来分析这个问题后就豁然开朗。

    按Ryan的方法,多IDC实现有以下几种思路。

    一、Master/slave

    这个是多机房数据访问最常用的方案,一般的需求用此方案即可。因此大家也经常提到“premature optimization is the root of all evil”。
    优点:利用mysql replication即可实现,成熟稳定。
    缺点:写操作存在单点故障,master坏掉之后slave不能写。另外slave的延迟也是个困扰人的小问题。

    二、Multi-master

    Multi-master指一个系统存在多个master, 每个master都具有read-write能力,需根据时间戳或业务逻辑合并版本。比如分布式版本管理系统git可以理解成multi-master模式。具备最终一致性。多版本数据修改可以借鉴Dynamo的vector clock等方法。

    优点:解决了单点故障。
    缺点:不易实现一致性,合并版本的逻辑复杂。

    三、Two-phase commit(2PC)

    Two-phase commit是一个比较简单的一致性算法。由于一致性算法通常用神话(如Paxos的The Part-Time Parliament论文)来比喻容易理解,下面也举个类似神话的例子。

    某班要组织一个同学聚会,前提条件是所有参与者同意则活动举行,任意一人拒绝则活动取消。用2PC算法来执行过程如下

    Phase 1

    Prepare: 组织者(coordinator)打电话给所有参与者(participant) ,同时告知参与者列表。
    Proposal: 提出周六2pm-5pm举办活动。
    Vote: participant需vote结果给coordinator:accept or reject。
    Block: 如果accept, participant锁住周六2pm-5pm的时间,不再接受其他请求。

    Phase 2

    Commit: 如果所有参与者都同意,组织者coodinator通知所有参与者commit, 否则通知abort,participant解除锁定。

    Failure 典型失败情况分析

    Participant failure:
    任一参与者无响应,coordinator直接执行abort
    Coordinator failure:
    Takeover: 如果participant一段时间没收到cooridnator确认(commit/abort),则认为coordinator不在了。这时候可自动成为Coordinator备份(watchdog)
    Query: watchdog根据phase 1接收的participant列表发起query
    Vote: 所有participant回复vote结果给watchdog, accept or reject
    Commit: 如果所有都同意,则commit, 否则abort。

    优点:实现简单。
    缺点:所有参与者需要阻塞(block),throughput低;无容错机制,一节点失败则整个事务失败。

    四、Three-phase commit (3PC)

    Three-phase commit是一个2PC的改进版。2PC有一些很明显的缺点,比如在coordinator做出commit决策并开始发送commit之后,某个participant突然crash,这时候没法abort transaction, 这时候集群内实际上就存在不一致的情况,crash恢复后的节点跟其他节点数据是不同的。因此3PC将2PC的commit的过程1分为2,分成preCommit及commit, 如图。

    (图片来源:http://en.wikipedia.org/wiki/File:Three-phase_commit_diagram.png)

    从图来看,cohorts(participant)收到preCommit之后,如果没收到commit, 默认也执行commit, 即图上的timeout cause commit。

    如果coodinator发送了一半preCommit crash, watchdog接管之后通过query, 如果有任一节点收到commit, 或者全部节点收到preCommit, 则可继续commit, 否则abort。

    优点:允许发生单点故障后继续达成一致。
    缺点:网络分离问题,比如preCommit消息发送后突然两个机房断开,这时候coodinator所在机房会abort, 另外剩余replicas机房会commit。

    五、Paxos

    Google Chubby的作者Mike Burrows说过, “there is only one consensus protocol, and that’s Paxos” – all other approaches are just broken versions of Paxos. 意即“世上只有一种一致性算法,那就是Paxos”,所有其他一致性算法都是Paxos算法的不完整版。相比2PC/3PC, Paxos算法的改进

    • P1a. 每次Paxos实例执行都分配一个编号,编号需要递增,每个replica不接受比当前最大编号小的提案
    • P2. 一旦一个 value v 被replica通过,那么之后任何再批准的 value 必须是 v,即没有拜占庭将军(Byzantine)问题。拿上面请客的比喻来说,就是一个参与者一旦accept周六2pm-5pm的proposal, 就不能改变主意。以后不管谁来问都是accept这个value。
    • 一个proposal只需要多数派同意即可通过。因此比2PC/3PC更灵活,在一个2f+1个节点的集群中,允许有f个节点不可用。

    另外Paxos还有很多约束的细节,特别是Google的chubby从工程实现的角度将Paxos的细节补充得非常完整。比如如何避免Byzantine问题,由于节点的持久存储可能会发生故障,Byzantine问题会导致Paxos算法P2约束失效。

    以上几种方式原理比较如下

    (图片来源:http://snarfed.org/space/transactions_across_datacenters_io.html)

    后文会继续比较实践环境选取何种策略合适。

    (PS: 写完后在Google Reader上发现本文跟王建硕最近发表的《关于两个机房的讨论》文章有点类似,特别是本文一、二方式。不过他的文章偏MySQL的实现,我的重点是一致性算法,大家可以有选择性的阅读。)

    Paxos在大型系统中常见的应用场景

    在分布式算法领域,有个非常重要的算法叫Paxos, 它的重要性有多高呢,Google的Chubby [1]中提到

    all working protocols for asynchronous consensus we have so far encountered have Paxos at their core.

    关于Paxos算法的详述在维基百科中有更多介绍,中文版介绍的是choose value的规则[2],英文版介绍的是Paxos 3 phase commit的流程[3],中文版不是从英文版翻译而是独立写的,所以非常具有互补性。Paxos算法是由Leslie Lamport提出的,他在Paxos Made Simple[4]中写道

    The Paxos algorithm, when presented in plain English, is very simple.

    当你研究了很长一段时间Paxos算法还是有点迷糊的时候,看到上面这句话可能会有点沮丧。但是公认的它的算法还是比较繁琐的,尤其是要用程序员严谨的思维将所有细节理清的时候,你的脑袋里更是会充满了问号。Leslie Lamport也是用了长达9年的时间来完善这个算法的理论。

    实际上对于一般的开发人员,我们并不需要了解Paxos所有细节及如何实现,只需要知道Paxos是一个分布式选举算法就够了。本文主要介绍一下Paxos常用的应用场合,或许有一天当你的系统增大到一定规模,你知道有这样一个技术,可以帮助你正确及优雅的解决技术架构上一些难题。

    1. database replication, log replication等, 如bdb的数据复制就是使用paxos兼容的算法。Paxos最大的用途就是保持多个节点数据的一致性。

    2. naming service, 如大型系统内部通常存在多个接口服务相互调用。
    1) 通常的实现是将服务的ip/hostname写死在配置中,当service发生故障时候,通过手工更改配置文件或者修改DNS指向的方法来解决。缺点是可维护性差,内部的单元越多,故障率越大。
    2) LVS双机冗余的方式,缺点是所有单元需要双倍的资源投入。
    通过Paxos算法来管理所有的naming服务,则可保证high available分配可用的service给client。象ZooKeeper还提供watch功能,即watch的对象发生了改变会自动发notification, 这样所有的client就可以使用一致的,高可用的接口。

    3.config配置管理
    1) 通常手工修改配置文件的方法,这样容易出错,也需要人工干预才能生效,所以节点的状态无法同时达到一致。
    2) 大规模的应用都会实现自己的配置服务,比如用http web服务来实现配置中心化。它的缺点是更新后所有client无法立即得知,各节点加载的顺序无法保证,造成系统中的配置不是同一状态。

    4.membership用户角色/access control list, 比如在权限设置中,用户一旦设置某项权限比如由管理员变成普通身份,这时应在所有的服务器上所有远程CDN立即生效,否则就会导致不能接受的后果。

    5. 号码分配。通常简单的解决方法是用数据库自增ID, 这导致数据库切分困难,或程序生成GUID, 这通常导致ID过长。更优雅的做法是利用paxos算法在多台replicas之间选择一个作为master, 通过master来分配号码。当master发生故障时,再用paxos选择另外一个master。

    这里列举了一些常见的Paxos应用场合,对于类似上述的场合,如果用其它解决方案,一方面不能提供自动的高可用性方案,同时也远远没有Paxos实现简单及优雅。

    Yahoo!开源的ZooKeeper [5]是一个开源的类Paxos实现。它的编程接口看起来很像一个可提供强一致性保证的分布式小文件系统。对上面所有的场合都可以适用。但可惜的是,ZooKeeper并不是遵循Paxos协议,而是基于自身设计并优化的一个2 phase commit的协议,因此它的理论[6]并未经过完全证明。但由于ZooKeeper在Yahoo!内部已经成功应用在HBase, Yahoo! Message Broker, Fetch Service of Yahoo! crawler等系统上,因此完全可以放心采用。

    另外选择Paxos made live [7]中一段实现体会作为结尾。

    *  There are significant gaps between the description of the Paxos algorithm and the needs of a real-world system. In order to build a real-world system, an expert needs to use numerous ideas scattered in the literature and make several relatively small protocol extensions. The cumulative effort will be substantial and the final system will be based on an unproven protocol.
    * 由于chubby填补了Paxos论文中未提及的一些细节,所以最终的实现系统不是一个理论上完全经过验证的系统

    * The fault-tolerance computing community has not developed the tools to make it easy to implement their algorithms.
    * 分布式容错算法领域缺乏帮助算法实现的的配套工具, 比如编译领域尽管复杂,但是yacc, ANTLR等工具已经将这个领域的难度降到最低。

    * The fault-tolerance computing community has not paid enough attention to testing, a key ingredient for building fault-tolerant systems.
    * 分布式容错算法领域缺乏测试手段

    这里要补充一个背景,就是要证明分布式容错算法的正确性通常比实现算法还困难,Google没法证明Chubby是可靠的,Yahoo!也不敢保证它的ZooKeeper理论正确性。大部分系统都是靠在实践中运行很长一段时间才能谨慎的表示,目前系统已经基本没有发现大的问题了。

    Resources
    [1] The Chubby lock service for loosely-coupled distributed systems (PDF)
    [2] http://zh.wikipedia.org/wiki/Paxos算法
    [3] http://en.wikipedia.org/wiki/Paxos_algorithm
    [4] Paxos Made Simple (PDF)
    [5] ZooKeeper
    [6] The life and times of a zookeeper
    [7] Paxos Made Live – An Engineering Perspective (PDF)