跳到主要内容

分布式一致性、共识概述

本文概要说明分布式系统的演进路线,并且说明在演进过程中引入的一致性问题的解决方案

1. 什么是分布式系统

一开始,所有的服务都在一个系统、部署在一台机器上,这时候是 单体应用。 随着业务的发展,会出现:

  • 功能上逻辑越来越多:规模增大导致软件极其复杂
  • 性能上用户越来越多:硬件上限 业务拆分和多副本部署就成了必然,就演变出集群应用微服务等架构。
分布式应用的界定:应用节点是否使用多个一致的信息池。

节点多不意味就是分布式系统。比如有很多节点的无状态计算服务,每个节点并没有协同,它只是一个集群,并不是一个分布式系统。

希望 分布式应用像一个单体应用般对外提供服务:

  • 分散功能和性能 (分区可用性、性能)
  • 不想分散服务 (一致性) 这个就是分布式系统一致性的问题。

总的来说,分布式系统相比单体应用新引入了如下问题:

  • 分布式一致性问题
  • 节点发现问题:服务注册/发现
  • 节点调用问题:RPC、网关
  • 节点协作问题:服务保护

2. 什么是一致性

分布式一致性定义:集群中某个节点上发生变更并经过一段时间后,能够从应用中的每个节点读取到这个变更。

关系型数据库中有一个 事务一致性,就是 ACID 中的 C。指的是 事务的执行不会破坏数据完整性约束。这个不是本文要讨论的一致性。

根据定义中 经过一段时间后 的时间长短,可以将一致性分为很多种(由弱变强):

  • 最终一致性:有限时间系统达到一致性状态
  • 线性一致性:单个节点的所有事件在全局事件历史上符合程序的先后顺序 且 全局事件历史在各个节点上一致
  • 顺序一致性:线性一致性 且 全局历史事件中 早结束的事件 在 晚开始的时间之前 (这个是分布式系统的最高追求)
  • 严格一致性:修改的瞬间同步到其他所有节点 —— 现实生活中做不到

线性一致性 常见算法有 两阶段提交、三阶段提交

两阶段提交就是把整个提交过程分成两个阶段(Two-Phase Commit, 2PC):

  1. Prepare:
    • 协调者向所有的参与者都发送 "Prepare" 消息,等到参与者响应
    • 参与者收到 "Prepare" 消息后将消息中的操作封装为事务,但是不提交,成功回复YES,失败回复NO
  2. Commit:
    • 如果协调者在规定时间内收到了所有的参与者的消息都是 YES,就给参与者发送 "Commit" 消息, 参与者开始提交事务,提交完成后回复DONE
    • 如果协同者收到了 NO,或者超时未收到,就给参与者 发送 "Rollback",参与者开始回滚事务,回滚完成后回复DONE

二阶段会有一些缺陷,又有三阶段提交(Three-Phase Commit, 3PC)

  1. CanCommit:
    • 协调者询问参与者能否完成操作(不开启事务)
    • 参与者回复 YES/NO
    • 如果存在NO或者有参与者超时未回复,协同者发送Abort,参与者不进人阶段2
    • (参与者可能规定时间内什么都没收到,那么也退出)
  2. PreCommit:
    • 协同者开始发送 PreCommit 消息,所有参与者开启事务但不提交成功后回复ACK,失败回复NO
    • 如果协同者没有在规定时间收到所有的ACK,就发送Abort
    • (参与者可能规定时间内什么都没收到,那么也退出)
  3. DoCommit:
    • 协同者开始发送 "Commit" 消息,参与者回复 Done
    • 如果协同者在规定时间内收到了所有的 Done,正常退出,不然发送 Abort

无论2PC还是3PC,都不完美

最终一致性 的算法有 BASE 定理。

分布式系统中有CAP理论:

  • Consistency:一致性
  • Availability:可用性
  • Parition Tolerance:分区容错性

CAP最多只能同时达到两个,当认识到CAP约束后。就产生了BASE定理来解决这个问题:

  • Basically Available:基本可用是指通过功能裁剪、性能降低等方法提供不完善的可用性
  • Soft State:不像硬状态中系统的状态是确定的,系统状态可能是模糊的
  • Eventually Consistent:软状态最终会变成硬状态(一致性)

3. 什么是共识

共识和一致性是两个紧密关联但是又彼此独立的概念。一致性是目的,共识只是分布式系统在实现一致性目的的过程中必然要经历的过程。

共识算法 Paxos最著名,Raft基于Paxos做了简化,被广泛使用。

Raft算法将所有的节点规定为三个状态:

  • Leader为唯一领袖,接收变更请求
  • Follower 接收领袖的心跳,是领袖的追随者,听从领袖的同步信息。启动时的默认状态
  • Candidate为正在竞选状态

包括两个阶段:

  • Leader选举阶段:
    • 如果Follower不能收到领袖的心跳,就进入Candidate状态开始竞选领袖。起先给自己投一票,然后开始找其他节点拉票
    • 其他Follower如果发现这个竞选者的信息领先自己,就把票投出去。一个竞选周期只投最早的那个竞选者
    • 如果竞选者票数超过一半,就成为新的领袖
    • (如果平票,再来一轮)
    • (旧的领袖发现自己任期更旧,自动退位为追随者)
  • 变更处理阶段:基于复杂状态机做的实现。当集群收到变更,交给Leader。Leader会按照顺序执行变更,实现便跟串行化。
    • Leader将变更追加到变更列表末尾
    • Leader将变更发送给执行完成前面变更的节点,等待回应
    • Leader收到半数节点的正确回应,就提交变更,并告知客户端