2021-08-08

一致性算法

为什么需要一致性算法

  • 分布式存储系统通常通过维护多个副本来提高系统的可用性和性能,要实现此目标,就必须维护多个副本的一致性

如何实现一致性算法

  • 一致性协议通常基于Replicated state machines,即所有结点都从同一个state出发,都经过同样的一些操作序列(log),最后到达同样的state

Replicated state machines

【图1, 论文中的一致性状态机】

  • 复制状态机通常都是基于复制日志实现的,如图 1。
  • 每一个服务器存储一个包含一系列指令的日志,并 且按照日志的顺序进行执行。每一个日志都按照相同的顺序包含相同的指令,所以每一个服务器都执行 相同的指令序列
  • 保证复制日志相同就是一致性算法的工作了

为什么需要用日志呢?

  • 日志可以记录操作的顺序
    • 让所有副本执行的操作的顺序相同
    • 让leader可以确定所有follower的log是相同的
  • log记录的是临时的记录,直到被commit
  • log可以记录发送过的command,就是leader重复发送某个command,也没影响
  • log的持久化,就算机器重启,也可以恢复之前的状态

所有副本见的日志都是一致的吗?

  • 不一定,有些副本可能会延迟,但他们最终都会一致
  • 一致性算法的规定,会执行那些被commit的command

raft

基础

  • 【先上图2】

  • 3种角色

    • follower,candidate,leader
    • 【论文图4】
  • 2个Rpc

    • requestVote
    • appendEntry
  • raft的leader选举

  • raft如何保证日志的一致

Leader election

  • 为什么需要leader?
    • 确保所有副本按同样的顺序执行command
  • 什么时候会发生选举
    • 当follower,在一个超时时间内没收到leader的AppendEntry心跳,就会变成candidate,并发起投票RequestVote
  • raft给leader进行term编号
    • 一个leader对于一个term
    • 通过term这个逻辑时间,可以让所有server之间比较,来找出最新的leader
    • term是递增的,一个term里最多有一个leader
  • 如何保证呢?
    • 需要获得多数server的投票,才能成为leader
    • 每个server在每个term,只能投一次票
    • 即使发生网络分区,或部分机器(2n+1个机器, 少于n)fail了,也能完成选举
  • 其他server如何感知新选举的leader呢?
    • 新leader会 发送AppendEntries 心跳,给其他机器
    • 这个心跳里带有 当前的,更高的逻辑时间 term
  • 选举失败(获取少于多数的投票)后,会发送什么?
    • 发起选举的机器,维护了一个election timeout的时间,超过这个时间没收到多数的投票,会再发起一次选举(term也更新)
  • 如何避免 split vote
    • 即所有机器同时发起选举–》同时选举失败–》同时超时–》再同时发起下次选举,,,,
    • 每个server 维护了一个 随机的超时时间
    • 这样就会有一个最快的server 完成选举,成为leader,发送 发送AppendEntries 心跳,给其他的server
  • 如果发生了网络分区,旧的leader无法感知新leader,会怎么办?
    • 能选出新leader,意味着获取了多数的投票
    • 新leader有更高的term
    • 旧leader的是更低的term,发起的appendEntry无法得到多数的返回
    • 因此旧leader无法commit log,无法更新state,因此没有脑裂

Log Replication

  • 通过appendEntry 的 来执行
  • 先看一些流程
    • client发送请求操作给leader
    • leader append 自己的日志
    • 给其它的server发AppendEntriesRPC
    • follower写自己的日志,然后恢复leader
    • leader等到了多数的回复后,标记这个日志是commited的了
      • commited 意味着是可以被apply 到state machien的log
      • 上面的多数,意味着,即使发生故障,下一个leader 也会有这个commited的log
    • leader 的下一个appendEntry 会带有“已经commited”的log的编号,follower收到后,也会进行apply操作

Log Compaction

  • 【论文图12】
  • 因为log会很多,不能让日志无限增长。
  • 整个系统进行snapshot来处理,snapshot之前的日志都可以丢弃
  • 每个副本独立的对自己的系统状态进行Snapshot,并且只能对已经提交的日志记录(已经应用到状态机)进行snapshot。

集群成员变化

  • 例如集群的集群数从5变为9

  • 如果直接改,会不安全,【论文图10】

  • 使用二阶段法

    • 目前有很多种两阶段的实现。例如,有些系统在第一 阶段停掉旧的配置所以集群就不能处理客户端请求;然后在第二阶段在启用新的配置。
    • 在 Raft 中,集 群先切换到一个过渡的配置,我们称之为共同一致;一旦共同一致已经被提交了,那么系统就切换到新的配置上
  • 共同一致是老配置和新配置的结合:

    • 日志条目被复制给集群中新、老配置的所有服务器。
    • 新、旧配置的服务器都可以成为领导人。
    • 达成一致(针对选举和提交)需要分别在两种配置上获得大多数的支持
  • 共同一 致可以让集群在配置转换的过程中依然响应客户端的请求

如何优化只读的操作

  • ReadIndex
    • 可以通过readindex 实现 follower read
    • follower 收到 read 请求之后,直接给 leader 发送一个获取 ReadIndex 的命令,leader 仍然走一遍之前的流程,然后将 ReadIndex 返回给 follower,follower 等到当前的状态机的 apply index 超过 ReadIndex 之后,就可以 read 然后将结果返回给 client 了。
  • LeaseRead
    • 相比readindex 无Heartbeat 的开销

https://pingcap.com/blog-cn/lease-read#page-content

https://pingcap.com/blog-cn/linearizability-and-raft#heading-4

一些用了raft的场景

  • redis 的哨兵选主
  • etcd
  • tikv

资料

  • 论文 https://pdos.csail.mit.edu/6.824/papers/raft-extended.pdf
  • https://zhuanlan.zhihu.com/p/27207160
  • http://www.kailing.pub/raft/index.html#home raft过程的动画
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值