2020-04-27

Paxos和Raft读优化 – Quorum Read 和 Read Index

Views: 13072 | Add Comments

在优化之前, 我们先分析原始的能保证正确性的做法是什么, 然后分析问题在哪, 最后再讨论怎么优化.

* Paxos 读流程: 针对要读取的对象, 在其操作序列中追加一条 read 共识.
* Raft 读流程: 在 Raft 日志序列中写一条 read 日志, 等 commit.

两者其实是一样的, 都是复制状态机模型, 都要复制一条 read 日志, 然后 apply 之后才能返回结果. 问题在哪呢? 很显然, 大部分系统是读多写少, 每一次读都需要达成共识, 而达成共识的过程无论是 Paxos 还是 Raft, 成本都太高了 - 网络写 IO, 磁盘写 IO. 既然是读操作, 能否只用磁盘读 IO 就行了呢? 这个想法就是优化的方向.

一致性算法的基础是, 无论客户端是什么操作, 集群都要在全部或者部分成员参与的情况下, 达成新的共识. 优化的思路是在某些情况下, 不用每一次操作都达成新共识. 怎么做到? 1, 如果全部成员都是一致的, 客户端读操作就没必要生成新的共识. 2, 读操作不主动生成新的共识, 而是等待其它客户端写操作生成新的共识.

Linearizable Paxos Quorum Read

流程分为: Quorum-read phase, Rinse phase.

1. 读取半数以上节点的 accepted_index, 记录其中 max_accepted_index
2. 等待, 直到任意一个节点 max_accepted_index 被 apply/execute, 以那个节点上的数据返回给客户端

重要的地方就是"等待", 如果没有等待, 就会变成简单的 Quorum Read, 是错误的. 这个读优化算法的正确名字应该是: 带有停止等待的多数派读. 区别于传统意义的"读多数派中的最新者". 其实叫"Read Index"更准确.

这里面其实有个问题, 因为 Paxos 是消极的, 如果没有外界触发, 这个等待可能永远也不会返回.

Raft Read Index

Leader 的数据就是可以返回的, 唯一的问题是, 某个节点可以错误地自认为是 leader, 所以要先确认自己是不是 leader.

1. 自认是 leader 的节点询问半数以上节点自己是不是 leader
2. 如果确认自己是 leader, 等状态机 apply 到大于等于 commitIndex(这个时刻就是 readIndex) 后, 读取状态机的结果返回
3. 如果发现自己不是 leader 怎么办? 找到正确的 leader, 获取 readIndex, 然后等待自己的状态机 apply 到至少 readIndex.

因为 Raft 是积极的, 所以AppliedIndex 一定会最终等于 commitIndex, 即使没有外界触发也不会永远等待.

无论是原始在往日志序列中追加日志, 或是 Linearizable Paxos Quorum Read 或 Raft Read Index, 本质就是插入一个同步点(memory barrier), 确保这个同步点和之前的日志已经 apply.

Related posts:

  1. Raft Read Index 的实现
  2. Paxos什么都包含, 也什么都不是
  3. Raft 为什么不能直接 commit 前任的日志?
  4. Paxos 和 Raft 的结构差异
  5. 为什么极少有开源的Paxos库?
Posted by ideawu at 2020-04-27 18:11:50 Tags: ,

Leave a Comment