读书笔记(SRE:Google运维解密):第23章 管理关键状态:利用分布式共识来提高可靠性

  • 在构建可靠的、高可用的系统过程时,分布式共识系统适合用来维护某个强一致的系统状态。
     
  • CAP理论: Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),论述了一个分布式系统不可能同时满足以下三个要求:
    (1)每个节点上所见数据是一致的。
    (2)每个节点都可以访问数据。
    (3)可以承受网络分区问题。
     
  • BASE理论:基本可用、软状态、最终一致性(basically available、softstate、eventual consistency)。
     
  • 系统设计师不能通过牺牲正确性来满足可靠性或者性能的要求,尤其是在处理关键数据时。

例如,假设某个系统处理财务交易:可靠性和性能在最终结果不正确的情况下一文不值。

 

  • 很多分布式系统问题最后都归结为分布式共识问题的不同变种,包括领头人选举,小组成员信息,各种分布式锁和租约机制,可靠的分布式队列和消息传递,以及任何一种需要在多个进程中共同维护一致的关键状态的机制。所有这些问题都应该仅仅采用经过正式的正确性证明的分布式共识算法来解决,还要确保这个算法的实现经过了大量测试。任何一种临时解决这种问题的方法(例如心跳,以及谣言协议)在实践中都会遇到可靠性问题。
     
  • Paxos概要:协议示例

Paxos 是基于提案(proposal)序列运行的,这些提案可能会被“大多数(majority)”进程所接受,也可能会被拒绝。如果某个提案没有被接受,那么它就是失败的。每个提案都对应有一个***,这就保证了系统的所有操作有严格的顺序性。
 
在协议的第一阶段,提案者(proposer)发送一个***给数个接收者(acceptor)。每个接收者仅仅在没有接受过带有更高***的提案情况下接受这个提案。提案者必要时可以用更高的***重试提案。提案者必须使用一个唯一的***(每个提案者从不相交的集合中提取***,或者将自身的主机名加入到***中等)。
 
如果提案者从“大多数”接收者那里接收到了“同意”回复,它便可以通过发送一个带有值的提交信息(commitmessage)来尝试提交这个提案。
 
提案的严格顺序性解决了系统中的消息排序问题。需要“大多数”参与者同意才能提交提案的要求保证了一个相同的提案无法提交两个不同的值,因为两个“大多数”肯定会至少重合一个节点。当接收者接收某个提案的时候,必须在持久存储上记录一个日志(journal),因为接收者必须在重启之后仍然保持这个状态。
 
Paxos本身来说不那么好用,它仅仅能够做到让节点共同接收一次某个值和提案号码。因为共同接收该值的节点数可以仅仅是“法定人数”(quorum)(也就是总数的一半再加1),任何一个节点可能都没有一个完整的视图,不知道目前已经被接收的所有的值。这个限制在大部分分布式共识算法中都存在。

 

  • 很多成功使用分布式共识算法的系统常常是作为该算法实现的服务的一个客户端来使用的,例如ZooKeeper、Consul,以及 etcd。
     
  • 分布式系统的领头人选举是跟分布式共识等价的问题。
     
  • 分布式锁可以保障多个工作进程不会操作同一个输入文件。在实践中,使用可续租约(renewable Lease)而不是无限时间锁是很有必要的,避免某个进程崩溃而导致锁无限期被持有。
     
  • 原子性广播是分布式系统的一个原语,意思是整个系统的参与者都可以可靠地接收到消息,并且以同样的顺序来处理这些消息。这个概念在真实系统的设计中是非常有用的。
     
  • 在共识系统中,系统负载可能会从以下几个方面发生变动。
    • 吞吐量:在负载峰值时,单位时间内提出提议的数量。
    • 请求类型:需要修改状态的写请求的比例。
    • 读请求的一致性要求。
    • 如果数据大小可变,请求的大小。

部署策略也有很多可变之处,例如:

  • 局部区域部署,还是广域部署?
  • 采用的是哪种仲裁过程,大部分进程的分布情况如何?
  • 该系统是否使用分片、流水线和批处理技术?

 

  • 基本的复合式Paxos 消息流
    读书笔记(SRE:Google运维解密):第23章 管理关键状态:利用分布式共识来提高可靠性

组内的另外一个进程可以在任何时间提交消息,并成为一个新的提议者,但是提议者角色的更换会带来性能上的损失。首先系统需要额外的时间重新执行协议的第一阶段部分,更重要的是,更换提议者可能会造成一种“提议者决斗”的状况。在这种状况下,两个提议者不停地打断对方,使得没有一个新的提议可以被成功接收。这种场景是一种活跃死锁的场景,可能会无限进行下去。

读书笔记(SRE:Google运维解密):第23章 管理关键状态:利用分布式共识来提高可靠性

所有实用的共识系统都必须解决这种冲突问题,通常是要么选举一个固定的提议者进程(也就是领头人),负责发送系统中的所有提议,要么使用一个轮换机制,给每个进程划分特定的提议槽。

 

  • 为了保障读取的数据是最新的,包含在该读取操作执行之前的所有改变,以下几条中的一条必须要满足:
    (a)进行一次只读的共识操作。
    (b)从一个保证有最新数据的副本读取数据。在使用稳定领头人进程的系统中(大部分分布式共识系统都会有),该领头人进程就可以提供这种保障。
    (c)使用法定租约(quorum lease)协议,在该协议下,某些副本被授予部分或者全部数据的一个租约,用一些写性能上的损失换来了强一致性的本地读操作的可能。该技术在接下来的一节中会详细描述。
     
  • 法定租约技术针对数据的一部分给系统中的法定人数进程发放了一个租约,这个租约是带有具体时间范围的(通常很短)。在这个法定租约有限期间,任何对该部分数据的操作都必须要被法定租约中的所有进程响应。如果租约中的任何一个副本不可用,那么该部分数据在租约过期前将无法被修改。
  • 法定租约对大量读操作的系统是非常有用的,尤其是当数据的某一部分是被集中在某一个地理区域的进程所读取的时候。
     
  • 分布式共识系统的性能问题
    • 两个主要的物理限制
      • 网络往返时间(RTT)
      • 数据写入持久化存储的时间

传统理念经常认为分布式共识算法速度太慢,资源要求过高,不适合用于搭建高吞吐量并且低延迟的系统。这种观点是错误的—虽然某些分布式共识系统的实现比较慢,但是有很多办法可以提高性能。

 

  • 分布式共识系统的部署副本的数量

一般来说,共识系统都要采用“大多数”的法定过程。也就是说,一组2f+1副本组成的共识组可以同时承受f个副本失败而继续运行(如果需要容忍拜占庭式失败,也就是要能够承受副本返回错误结果的情况,则需要3f+1个副本来承受f个副本失败)。针对非拜占庭式失败的情况,最小的副本数量是3—如果仅仅部署两个副本,则不能承受任何一个副本失败)。3个副本可以承受1个副本失败。
 

  • 针对任何 分布式共识系统的副本数量的考虑都是基于以下几个因素中的一个进行妥协:
    • 对可靠性的要求
    • 计划内维护操作的频率
    • 危险性
    • 性能
    • 成本
       
  • 为了更好地理解分布式共识系统性能,以及帮助进行故障排查,监控以下几点:
    • 每个共识组中的成员数量,以及每个成员的状态(健康或不健康)
    • 始终落后的副本
    • 领头人角色是否存在
    • 领头人角色变化的次数
    • 共识交易记录数字
    • 吞吐量和延迟
    • 针对提议接收时间的延迟分布。
    • 系统不同部分之间观察到的网络延迟。
    • 接收者在持久化日志上花费的时间。
    • 系统每秒处理的字节数。