Pulsar 的共识机制和成员管理

Pulsar 的共识机制和成员管理

参考:

https://medium.com/splunk-maas/apache-bookkeeper-insights-part-1-external-consensus-and-dynamic-membership-c259f388da21

Jack Vanlightly 的这篇博客虽然是讲的BookKeeper,但实际上,整体还是Pulsar的内容偏多。因为单纯的BookKeeper本身并不涉及到共识机制和成员管理的内容。

共识机制与存储分离

对比一下 Raft 和 Kafka 的共识方式,如下图,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-14-07-50.png

Raft 和 Kafka 的参与共识的节点和数据存储的节点是合一的,一个节点即参与共识,也完成数据存储。数据写入请求都是先发送到 Leader 节点,再同步到 Follower 节点。这样的设计,成为内置(internal)共识机制。

这个设计的一个很大的问题就是集群的成员管理相对固定,博客的原文是,

A byproduct of replication being performed by stateful fully integrated nodes is that cluster membership is relatively static.

如果想要增加或者删除节点,就会比较受限,非常麻烦。Pulsar 的设计是不一样的,分离了共识节点和存储节点。存储节点是单纯的存储功能,不需要处理自己在共识机制中的角色(实际上也没有角色),也不需要处理存储数据复制的问题。共识机制放在了客户端,也就是 Pulsar Broker 上处理,如下,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-14-26-04.png

对 Bookie 节点来说,Bookie 本身只是存储,提供通用的 Entry 存储功能。共识机制放在 Broker 处理,也就是说,Broker 在维护 Leader 的角色。

对 Raft 来说,如果节点故障一段时间后恢复,只需要将 Leader 节点上的数据复制过去就可以恢复节点,但 Pulsar 的 Leader 因为没有存储数据,处理起来就会非常麻烦(后文详述)。

但是因为分离了共识机制和存储,也会带来好处,Broker 可以快速的改变成员,来应对数据节点的故障,这个特性称为动态成员管理。那 Pulsar 是如何实现动态成员管理的特性的呢?

Commit Index

比较 Raft、Kafka、Pulsar,这三者都有 Commit Index 的概念,虽然在不同系统中的名称不一样。其基本特点是,都需要达到一定数量的写入成功,才可以确认 Commit Index,比较一下,

  • Raft 需要集群的大多数节点确认,才可以 Commit Entry;
  • Kafka 需要 min-insync-replicas 个确认,才能确认持久化成功;
  • Pulsar 需要 Ack Quorum (AQ) 个确认,才确认 Commit Entry;

为了方便描述,这个数量在后文统一称为提交数量(Commit Quorum)。

数据确认提交后,会返回 Entry Log 中提交成功的点,Raft 称呼这个点叫 Commit Index;Kafka 称之为高水位(High Watermark);BookKeeper 称之为 LAC(Last Add Confirmed)。这个机制的存在主要是保护各个节点数据的一致性。

对于 Raft 和 Kafka,Commit Index 是和数据一起从 Leader 传输到 Follower,最后,所有的节点都更新到了 Commit Index 和数据。Leader 对 Commit Index 的认知是略微超前 Follower 的,但通常情况下,这也没问题。如下图,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-14-57-26.png

对 Pulsar 来说,存储和共识机制是分离的,LAC 需要存储在 Bookie 中,但这些信息对 Bookie 来说几乎是没有用的。写入的过程也比较有特色,顺序是:写入数据 -> 更新 Leader Broker 的 LAC -> 更新 Bookie 的 LAC 存储。相比 Raft 和 Kafka,要多了一个步骤,不过由于可以流水线组合处理,实际性能也不会差。如下图,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-14-59-14.png

Raft Commit Index 的部分似乎并不精确,Raft 会收到大多数节点的 Ack 之后,才会更新 Commit Index。Leader 当然会比 Follower 更早知道下一个 Commit Index,但只有收到 Follower 的 Ack,才可以确认这个 Commit Index。

Kafka 的数据副本特性

动态成员管理可以解决什么样的问题?主要是副本创建、数据复制的灵活性,先看看 Raft 的例子。

当部分节点缓慢,或者故障的时候,由于 Raft 选择的是相对固定的成员管理方案,无法及时变更成员。为了提升系统整体的可用性,只能放弃一些安全性,选择了在有少量节点,不超过一半,有故障的前提下,依然可以提供服务。

Kafka 的选择也很类似,只要 min-insync-replicas 个节点能正常运行,就可以提供服务,不需要整个副本集合完全正常运行。

但是,这样的选择会破坏 liveness。liveness 是分布式算法领域的属性,用来衡量分布式算法的好坏,比如,

  • liveness: something good eventually happens. 或者说,算法期望的结果最终将发生;
  • safty: nothing bad happens. 或者说,不会发生恶性结果;

对 Raft 和 Kafka 来说,liveness 要求,数据将在所有节点上最终复制成功。达到这个目标,有以下一些事实前提,

  1. Entry 按时间顺序追加在 Leader 的日志/Entry文件中;
  2. Leader 将日志/Entry发送给 Follower,要求 Follower 按同样的顺序进行存储;
  3. 提交的日志/Entry达到大多数(Raft),或者 min-insync-replicas(Kafka) 个时,就不考虑丢失;
  4. Follower 节点上的日志/Entry文件和 Leader 完全一致,特指从 Commit Index 开始往前的部分;

对于这样一个复制机制,从第一个节点写入 Entry 开始,到 Entry 复制到所有副本上,Entry 通常会处于3种状态,如下,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-15-54-02.png

最开始,Entry 追加到头部,但还没有更新 Commit Index,可能丢失;然后,Leader 收到足够多的 Ack,更新 Commit Index,Entry 就持久化到了足够多的副本中,不会丢失了;最后,Entry 持久化到了所有副本中,处理完成。从上图来看,在系统运行的任何一个时刻,我们有,

Uncommit Index(Head) >= Commit Index >= Full-replicated Index

对系统使用来说,我们希望 Uncommit Index(Head)、Commit Index、Full-replicated Index 尽量接近,Tail 部分尽量大。但事与愿违,如果几个节点中,有一个比较慢,始终追赶不上其他节点同步副本的速度,或者有一个节点故障后丢失数据,需要从零开始恢复,这个时候,我们只能依赖副本复制机制。在复制期间,liveness 是受损的。

Pulsar 的数据副本特性

Pulsar 是通过写入数量(Write Quorum)和响应数量(Ack Quorum)来管理副本的,细节这里不介绍了。

对 Pulsar 来说,分离共识机制和存储,使得共识机制在无存储的 Broker 上实现,当发现一个 Bookie 节点不可用的时候,就马上选取另一个 Bookie 替代。如下,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-16-30-53.png

对集群的整体改动,也就是修改一下 Zookeeper 中账本的元数据,然后重新发送一下 Uncommitted Entry 去新 Bookie 就好了(因为已经 Commit 的 Entry 认为不需要再同步了)。这会导致 Ledger 的数据被分成多份,称之为 Fragment,放在多个 Bookie 上。每次有 Bookie 故障,就发起成员变更,并切分一个 Fragment 出来,以应对这个问题。如下图,一个 Ledger 分为了4个 Fragment,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-16-37-54.png

当仔细分析 Ledger 头部的 Entry 存储时,我们会发现结构和 Kafka 类似,如下,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-16-40-31.png

当成员变更发生时,Bookie 会丢弃尚未达到 Ack Quorum 的 Entry,只保留 Commit Index 之前的部分。新的 Bookie 从 Commit Index 之后开始,如下图,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-16-45-11.png

成员变更时,Pulsar 并不会处理 Full-replicated Index 和 Commit Index 之间的数据,于是导致 Bookie 上多个 Fragment 的存储可能尾部出现空洞,变成这样,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-16-50-46.png

Pulsar 不在成员变更的时候处理这个空洞的原因也是很自然的,因为很有可能此时 Bookie 处于故障阶段,Pulsar 即使想补足数据也是很难做到的。空洞的数据最终会由单独的恢复程序补足,但这并不是主流程的一部分。对比一下 Kafka 和 Pulsar 的存储结构图,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-16-57-31.png

虽然 Pulsar 的存储中间会发生空洞,但是当发现节点无法及时返回的时候,Pulsar 会立刻开始调整成员,恢复到正常的副本数,所以每个空洞都不会很大;而 Kafka 的存储虽然没有空洞,但是可能出现 Full-replicated Index 远远落后于 Commit Index 的情况。可见 Pulsar 的设计对系统整体的 liveness 有改进。

当 WQ=AQ 时

出于数据安全性的考虑,可能 WQ=AQ 是一个选择。假设 WQ=AQ=3,如果有节点发生故障,我们可以得到下图,

20220115-Pulsar 的共识机制和成员管理-2022-01-17-17-08-17.png

可以看到,由于 WQ=AQ,那么,就始终有 Commit Index == Full-replicated Index,不会有节点处于未被完全同步的状态。如果 Bookie 发生故障,还是从 Commit Index 开始新的 Fragment,数据的空洞问题解决了。当然,这个方法也有问题。

比如,必须准备有足够多的 Bookie 节点,否则当节点故障的时候,如果没有新 Bookie 的加入,就无法继续运行。

还有,可用性会有小幅度降低,因为在成员变更的时候,取决于 Zookeeper 操作的性能,在此期间,Broker是无法运行的。

注:这两个原因有些似是而非,在 AQ < WQ 的时候,也会有一样的问题。当 AQ < WQ 时,如果发生故障,会延迟一段时间进行成员变更,这一小段的可用性是可以保证的,但这个时间几乎可以忽略不计。还有,因为 Ack 数量增多,系统延迟必然变大,但是如果 Bookie 的性能可以跟得上的话,其实延迟问题应该不显著。
虽然,从系统整体上来看,我也认为 AQ < WQ 是最佳实践。

后记

Pulsar 的动态成员管理功能是一个很好的功能,但是其来源并不是存储与共识机制分离,而是单 Topic 多 Ledger,单 Ledger 多 Fragment 等特性的一个具体的应用而已。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • Pulsar 架构的的疑问和改进 本文会讨论 Pulsar 整体架构的一些疑问和可能的改进,一家之言。当前的 Pu...
    褚哥说阅读 1,419评论 0 2
  • Pulsar工作原理 参考文档: Pulsar: https://jack-vanlightly.com/blog...
    褚哥说阅读 1,698评论 0 0
  • 转载声明:本文来自微信公众号:火龙果园长,仅供学习交流,禁止用于商业用途,转载需关注公众号取得文章作者同意。 写在...
    火龙果园长阅读 7,318评论 0 18
  • 共识机制 什么是共识机制 区块链作为一个去中心化的分布式账本系统,然而在实际运行中,怎么解决因为去中心化后,保证整...
    HeartGo阅读 3,027评论 0 1
  • 背景 在人工智能技术的支持下,BIGO 基于视频的产品和服务受到广泛欢迎,在 150 多个国家/地区拥有用户,其中...
    StreamNative阅读 1,715评论 1 5