浅谈分布式一致性协议 | 青训营笔记

57 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第5天

1 分布式系统

1.1 分布式系统面临的挑战

  • 数据规模越来越大
  • 服务的可用性要求越来越高
  • 快速迭代的业务要求系统足够易用

1.2 理想中的分布式系统

  • 高性能:可拓展、低时延、高吞吐
  • 正确:一致性、易于理解
  • 可靠:容错、高可用

1.3 案例 KV

从最简单的单机KV系统开始

  • 接口:

    • Get(key) -> value
    • BatchPut([k1,k2……],[v1,v2……])
  • 第一次实现

    • RPC
    • DB Engine
  • 可靠性:

    • 容错?无
    • 高可用?无
  • 正确性:

    • 单进程,所有操作顺序执行

2 一致性与共识算法

2.1 从复制开始

打造一个可靠的KV系统,一台服务器可能会挂,那么最简单的,我们用两台服务器,使他们保持完全一致

如果有两个副本,那么他们都能接受请求吗?答案是最好不要,否则会出现下面的交叉复制的情况,难以保证数据的可靠

2.2 如何复制

一个主副本,其他是从副本,操作箭头是单向的,有两种简单的复制方式

一种是主副本定期拷贝全量数据到从副本,因为全量拷贝代价很高,所以我们定期进行,但是定期会造成另一个问题,如果主副本刚写完,还没来得及拷贝到从副本就挂了

另一个是主副本拷贝操作到从副本

2.3 如何复制操作

  • 主副本把所有操作打包成Log

    • 所有的Log写入都是持久化的,保持在磁盘上
  • 应用包装成状态机,只接收Log作为Input、

  • 主副本确认Log已经成功写入到副本机器上,当状态机apply后,返回客户端

2.4 关于读操作

  • 方案一:直接读状态机,要求写操作进入状态机后在返回client
  • 方案二:写操作复制完后直接返回,读操作Block等待所有pending log 进入状态机
  • 如果不遵循上面两种方案,可能存在刚刚写入的值读不到的情况(在log中还没到状态机中,只有log输入到了状态机中才能被读到)

2.5 什么是一致性

  • 对于我们的KV系统

    • 对于多个副本用户感知像是在操作一台机器,要能读到最近写入的值
  • 一致性是一种模型(或语义)

    • 来约定一个分布式系统如何向外界(应用)提供服务

    • KV 中常见的一致性模型

      • 最终一致性:读取可能暂时读不到但是总会读到
      • 线性一致性:最严格,线性执行
  • 一致性分类:

    • 经常与应用本省有关,下图是数据库里面常出现的一致性的概念,从下到上越来越严格,最上面的线性一致性是最理想的

2.6 复制协议-当失效发生

  • 当主副本失效

    • 手动切换到从副本
    • 容错?没有,我们的服务还是停了
    • 高可用?也许是,取决于我们从发现到切换的过程有多快
    • 正确?是的,操作只从一台机器上发起。所有操作返回前都已经复制到另一台机器了
  • 当主副本失效时,为了使得算法简单

    • 我们人肉切换,只要足够快,我们还是可以保证较高的可靠性
  • 但是如何保证主副本真的失效了呢?

    • 在切换的过程中,挂掉的主副本又开始接收client端的请求,两个主副本显然是不正确的,log会被覆盖写掉,我们希望算法能在这种场景下仍然保持正确
  • 要是增加到三个节点呢?

    • 能不能允许少数节点挂了的情况下,仍然可以工作 falut-tolerance

2.7 共识算法

  • 什么事共识算法

    • "The consensus problem requires agreement among a number of processes (or agents) for a single data value. Some of the processes (agents) may fail or be unreliable in other ways, so consensus protocols must be fault tolerant or resilient"
    • 简而言之一个值一旦确定,所有人都认同
  • 容错(falute tolerance)

  • 有文章证明是一个不可能的任务(FLP impossibility) "In this paper, we show the surprising result that no completely asynchronous consensus protocol can tolerate even a single unannounced process death. We do not consider Byzantine failures, and we assume that the message system is reliableit delivers all messages correctly and exactly once." -- JACM 85 [1]

  • 错误总是发生 Non-Byzantine fault

  • 错误类型很多:网络断开,分区,缓慢,重传,乱序,CPU、IO 都会停住

  • 共识协议不等于一致性

    • 应用层面不同的一致性,都可以用共识协议来实现,比如可以故意返回旧的值,简单的复制协议也可以提供线性一致性
  • 一般讨论共识协议时提到的一致性,都指线性一致性

    • 因为弱一致性往往可以使用相对简单的复制算法实现

3 一致性案例:Raft

4 实现细节以及未来