查看原文
其他

博文干货|5张图带你快速入门 Pulsar 的存储引擎 BookKeeper

ApachePulsar 2024-03-31

The following article is from 程序员jinjunzhu Author jinjunzhu

关于 Apache Pulsar

Apache Pulsar 是 Apache 软件基金会顶级项目,是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体,采用计算与存储分离架构设计,支持多租户、持久化存储、多机房跨区域数据复制,具有强一致性、高吞吐、低延时及高可扩展性等流数据存储特性。
GitHub 地址:http://github.com/apache/pulsar/

本文转自公众号:程序员 jinjunzhu,作者:jinjunzhu
本期排版:StreamNative@Tango

Apache BookKeeper 是一款企业级存储系统,最初由雅虎研究院研发,在 2011 年作为 Apache ZooKeeper 的子项目进行孵化,在 2015 年 1 月成为 Apache 顶级项目。

起初,BookKeeper 是一个预写日志(WAL)系统,经过几年的发展,BookKeeper 的功能更加完善,比如为 Hadoop 分布式文件系统(HDFS)的 NameNode 提供高可用和多副本,为消息系统比 Pulsar 提供存储服务,为多个数据中心提供跨机器复制。https://github.com/apache/pulsar/pull/11498

使用场景

BookKeeper 最初的一个使用场景是为 HDFS 的 NameNode 保存 edit log,如下图:

ZKFC 是一个 ZooKeeper 的客户端,主要用来监测和管理 NameNode 状态,每个 NameNode 机器上都会运行一个 ZKFC,它的职责主要有三个:

•健康检查•ZooKeeper 会话管理•选举,当集群中一个 Active NameNode 宕机,ZooKeeper 会自动选择一个节点作为新的 Active NameNode。

BookKeeper 记录 NameNode 的 edit log(edit log 存放文件系统的操作日志),NameNode 的所有修改都会记录到 BookKeeper。这样 active NameNode 宕机后,BookKeeper 用保存的 edit log 去 standby NameNode 做回放,之后切换成 active NameNode。

BookKeeper 具有如下特性:

•一致性:因为 edit log 保存的是 HDFS 的元数据,对一致性要求很高•低延迟:为了不丢数据,需要低延迟•高吞吐:为了支持更多的 NameNode 节点,需要高吞吐

节点对等

Bookie 中保存的数据结构如下图:

writer 写数据时,把 entry 并发写入多 个 bookie 节点的 Ledger。这类似于文件系统写数据时首先会打开一个文件,如果文件不存在,则会创建文件元数据。

Ledger 也就是 Pulsar 中的 segment。

writer 写数据时,首先会打开一个新 Ledger,函数如下:

openLedger(组内节点数目、数据备份数目、等待刷盘节点数目)

比如(5,3,2)代表组内共有 5 个 Bookie 节点,写数据时需要写入 3 个节点,有 2 个节点返回成功代表写入成功。

这样写入的这 3 个节点数据完全一样,关系是对等的,不存在主从关系。

数据读写

BookKeeper 数据读写如下图:

writer 以 roundrobin 的方式写入 bookie,比如在上图中,第一条数据写入 Bookie1、Bookie2 和 Bookie3,第二条数据写入 Bookie2、Bookie3、Bookie4,第三条数据写入 Bookie3、Bookie4、Bookie5,第四条数据写入 Bookie4、Bookie5 和 Bookie1。

在打开一个 Ledger 时,就传入了 bookie 数量,这样在写每个 entry 时,就用 entry 的 id 跟 bookie 数量取模,来确定写到哪几个 bookie 上。比如第 3 条消息跟 5 取模是 3,就写到 Bookie3、Bookie4 和 Bookie5。

这样以轮询的方式将 Ledger 数据写入各个 bookie 节点,每个 bookie 节点的数据是均衡的,每个 bookie 节点的磁盘带宽和网卡带宽都能得到充分利用。

读高可用

Reader 在读取数据时,可以读取多份数据中的任意一份数据。BookKeeper 会设置一个读超时时间,如果读取超时了,会给另外一个 bookie 节点(speculative read)发送读请求。

写高可用

如果某个 bookie 节点(比如 bookie5)发生故障不能写入了,BookKeeper 会做如下处理:

•记录出错的 entry id•对故障节点的数据进行封装•关闭当前的 Ledger,重新打开一个新的 Ledger,这个 Ledger 会重新选择 bookie 节点,1、2、3、4、6。•如果 bookie5 恢复,就不再提供写服务了,只提供读服务。•如果不能恢复,就把 bookie5 的数据,从其他节点的备份中恢复到新的节点上,这个过程需要根据 Ledger id 跟 5 取模来判断是否落到 bookie5 上,数据恢复过程并不影响 Reader,因为其他两份数据可以继续提供服务。

I/O 模型

BookKeeper 的 I/O 模型如下图,这个图是单个 bookie 的数据流转:

整个流程入下:

•Writer 写入的数据首先到达 Journal,Journal 将数据进行 group 后刷到到 Journal 盘,这个刷盘的数据顺序跟 writer 写入顺序一致。

Writer 写入 Journal Disk 是实时刷盘。

•Journal Disk 的数据会写入 memory table 进行数据整理,把同一个 topic 的数据整理到一起。•把整理好的数据刷盘。Index Disk 保存 entry 的 index,对应 entry 在 Logger Disks 的 offset。

读写分离

读取数据时,首先从 Memory Cache 中读取数据,如果数据不存在,才会去 Index Disk 和 Logger Disk 读取数据。而写数据是实时落盘到 Journal Disk,这样实现了读写隔离。

强一致性

数据可以实时刷盘到 Journal Disk,保证了数据的强一致性。

灵活 SLA

对于写性能要求高的业务场景,可以单独加强 Journal 盘性能,而对于读性能要求高的场景,可以加强 Ledger Disk 和 Index Disk 的性能。

Pulsar 中的使用

Pulsar 的架构图如下:

每次 Producer 生成的消息实时落盘后,给 Producer 返回一个 ACK。

Consumer 消费消息后,还会修改 Cursor 中保存的 offset,并且也会记录到 BookKeeper。这样保证了 Cursor 的一致性。

相关阅读

为什么选择 Apache BookKeeper — Part 2为什么选择 Apache BookKeeper - Part 1

点击“阅读原文”,获取 Apache Pulsar 硬核干货资料!

继续滑动看下一个
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存