本文转自:DataFunTalk,分享嘉宾:翟佳,StreamNative 联合创始人
编辑整理:张晓伟 美团点评
导读:多数读者们了解 BookKeeper 是通过 Pulsar,实际上 BookKeeper 在数据库和存储场景都有着非常广泛的应用。BookKeeper 是 Pulsar 的底层存储,Pulsar 有着广泛数据入口,Pulsar 跟 Kafka 及各类 MQ(RabbitMQ、ACTIVEMQ)的较大区别是 Pulsar 是统一的云原生消息流平台,不但是分布式系统,而且做了存算分离,可以让用户在云的环境下,体验到云原生的优势,例如随意扩缩容、数据灵活迁移复制等。希望通过本文,让大家对 Pulsar 底层的 BookKeeper 有更深入的了解。
(点击上方图片观看回顾视频)
今天的介绍会围绕下面四点展开:
• BookKeeper 的简介
• BookKeeper 的特性
• BookKeeper 存储介质的演进
• BookKeeper 的社区资源
BookKeeper 的简介
业务场景需求的统一
Pulsar 里有很重要的概念是“统一”,这个统一的特性是由 BookKeeper 支持实现的。这里的统一是指需求的统一,在消息场景下,用户场景分两类:
第一类是线上业务场景,例如 1984 年诞生的 IBM MQ 到现在的各类开源 MQ 解决的是线上业务场景,这些 MQ 的服务质量会对业务服务质量有着直接的影响,所以这类需求对数据质量,例如对数据持久性、数据延迟、消费模型的灵活性有较强的要求。
第二类是大数据场景,例如 2010 年左右随着实时计算的广泛使用,Kafka 的这种高带宽和高吞吐使用需求。
由于面向场景不同、技术栈不同,这两种场景在业务上又同时存在,给业务带来不同的基础设施 API、不同的使用方式、不同系统的运维成本等问题。所以 Pulsar 针对这些问题,做了两层 API 的统一:既兼容 MQ 的并发消费模型,提供比较好的服务质量,同时通过底层存储层抽象,可以提供很高的吞吐和带宽,这就是我们要介绍的 Apache BookKeeper 项目。
Apache BookKeeper 简介
很多服务里都有日志,例如 MySQL 的 binlog 和 HDFS 的 namenode 的 editlog,都是对日志的一个抽象,而 BookKeeper 就是把这个抽象变成了一个分布式的服务,摆脱了对单机容量瓶颈的限制,把日志变成了可无限扩展的服务。BookKeeper 使用 packet source 协议和 ZooKeeper 的 zap 协议,通过 log append only 的方式实现了低延迟和高吞吐。在 APCP 里选择 CP,而 availability 是通过多副本并发的方式提供高可用,BookKeeper 有着低延迟、高吞吐、持久化、数据的强一致性、服务的高可用、单节点可以存储很多日志、IO 隔离等优势,针对这些特性在后文会展开介绍。
BookKeeper 的诞生
BookKeeper 也是 Apache 的一个项目,同样是由雅虎捐献诞生,原本是为了应对雅虎开源 HDFS 里元数据存储的需求。
下图是字节跳动技术文章的一个图,主要是呈现在字节跳动如何用 BookKeeper 支撑元数据服务,支撑起 EB 级别的 HDFS 集群。这个集群 DN 有好几万台,需要很多 NameNode,就需要一个可以保障 active/standby/observer NameNode 之间强一致性的日志服务,单机容量瓶颈下很难支撑这么大的体量时,引入了一个分布式的日志服务,这就是 BookKeeper 诞生的场景。随着 HDFS 大规模的问题开始出现之后,BookKeeper 成为了 HDFS 在 HA 上的刚需需求,例如在 EMC 内部的 HDFS 集群,也是用的 BookKeeper 来做 NameNode 的 editlog 服务。BookKeeper 是一种分布式场景下很常见的复制状态机的实现(通过复制 log,保持各个节点状态机的同步,A 节点持久化 log 后,把 log 同步到 B 节点,在 B 节点进行 log 的一个重放,让 B 节点达到跟 A 节点一样的一个状态)。由于在 HDFS 场景中,保存的只是 NN 的变更日志,所以算是元数据的元数据,对数据一致性、对吞吐、对时延的要求自然极高。
BookKeeper 使用案例
BookKeeper 也有局限性,是 append only 的一个抽象变成了分布式服务,相对而言比较底层。所以用户多是一些比较大的互联网公司或其他有大数据量的需求的用户,这些用户会在 BookKeeper 之上做一些二次开发,例如 Pulsar 在 BookKeeper 之上做了一层 broker 服务,对 BookKeeper 的每个分片做一些管理然后将其作为数据的存储服务。
类似的还有 Twitter 和 Salesforce。Twitter 的技术栈是构建在实时计算上的,在 Twitter 内部,BookKeeper 是作为很重要的基础设施,不但有类似 Pulsar 的服务 eventbus,还有其他使用场景例如搜索、广告、Stream computing, 以及作为类似 KV 存储的 Manhattan Database 的元数据服务,这些场景都用到了 BookKeeper。在规模上,Twitter BookKeeper 有两个集群,每个集群约有 1500 个节点,每天有 17PB 的数据,每秒 1.5 万亿的 records。而在 Salesforce 的使用背景,是 Salesforce 想去掉对 Oracle 的依赖,所以自研了类似 Amazon Aurora 的 NewSQL Database,其内部很多跟元数据相关或有一致性要求的服务都是通过 BookKeeper 来满足的,并且也有部分后端场景将 BookKeeper 作为存储服务去用。
BookKeeper 的特性
BookKeeper 基本概念
Ledger
可以理解为 BookKeeper 是会计,Ledger 是账本,每个账本是记录信息的一个单元,写完之后转为 closed 状态(只读),最新的账本是打开状态(openLedger),以 append only 的方式持续存储数据。
Fragment
可以理解为 BookKeeper 内部维护的一个以 append only 的方式添加的数据组。
Fragment 之下就是用户以 append only 的方式追加的一条条数据。
BookKeeper 的节点对等架构
openLedger 时有 3 个参数:Ensemble 选择几个节点存储这个账本,Write Quorum 控制数据写几个副本(并发写,不同于 Kafka 或 HDFS,BookKeeper 没有数据节点之间主从同步的关系,把数据同步的协调者从服务端移到了客户端),Ack Quorum 控制等几个副本返回 ack。
以下图为例 openLedger(5,3,2),在保存这个账本时,选择了 5 个节点,但是只写 3 个副本,等 2 个副本来返回 ack。第一个参数一般可用于调整并发度,因为写 3 个副本是通过轮转的方式写入,例如第 1 个 record 是写 1-3 节点,第 2 个 record 写 2-4 节点,第 3 个 record 写 3-5 节点,第 4 个 record 写 4-5 和 1 节点这样轮转。这种方式即便 3 个副本,也可以把 5 个节点都用起来。
这几个参数便捷的特性可让用户通过机架感知、机房感知、resource 感知等各种方式进行灵活设置。当选好节点后节点之间的排序就已完成,每个 record 会带个 index,index 和节点已有绑定关系,例如 index 为 1 的,都放在 123 上,为 2 的都放在 234 上。通过这种方式可以让我们知道每个节点存了哪些消息,当某个节点宕机,根据这个节点的位置信息,把对应 record 还在哪些节点上有副本的信息找出来进行多对多的恢复。这么做的另一个好处是不用再维护元数据信息,只需要有每个节点记录 index 信息,在 openLedger 时记录好每个节点的顺序即可。
openLedger(5,3,2)数据存储结构就是下图中右边的结构,如果选择 Ensemble=3,Write Quorum=3,数据存储结构就是下图左边的结构:
综上,用户可以通过 Ensemble 来调整读写带宽,通过 Write Quorum 调整强一致性的控制,通过 Ack Quorum 权衡在有较多副本时也可以有较低的长尾时延(但一致性就可能有一定的损失)。
BookKeeper 可用性
读的高可用
读的访问是对等的,任意一个节点返回就算读成功。这个特性可以把延迟固定在一个阈值内,当遇到网络抖动或坏节点,通过延迟的参数避障。例如读的延迟时间 2ms,读节点 3 超过 2ms,就会并发地读节点 4,任意一个节点返回就算读成功,如下图 Reader 部分。
写的高可用
在 openLedger 时会记录每个节点的顺序,假如写到 5 节点宕机,会做一次元数据的变更,从这个时间开始,先进行数据恢复,同时新的 index 中会把 5 节点变为 6 节点,如下图 x 节点替换 5 节点:
BookKeeper 一致性
BookKeeper 底层节点对等设计让写入数据的 Writer 成为了协调者,Writer 来保存数据是否存储成功的状态,例如节点是否出现问题、副本够不够、切换 Fragment 时要不要做数据恢复、在写入过程中出现宕机时,通过 fencing 的方式防止脑裂等。所以,Writer 维护了 2 个 index:LastAddPushed 和 LastAddConfirmed。
LastAddPushed 会随消息 ID 递增,LastAddConfirmed 则记录最后一个连续的消息成功写入了(例如 Ack Quorum 为 2,有 2 个成功返回了即为成功),但因为返回顺序不一定与消息顺序一致,例如 123 个消息,3 的消息先返回了,2 的还未返回,按连续的规则就是 2 不是 3。
BookKeeper 与 Raft 的对比
在底层原理上,Raft 与 BookKeeper 有很多类似的地方,Raft 每个数据写入的组织形式是 term,跟 BookKeeper 的 segment 类似,每个 term 也会选择一组节点存储数据,然后不断往后追加数据,通过数据节点之间的协同保证数据一致性。
在数据结构上,Raft 在保存数据时有 Entry,Entry 除了带本身的 index 还会带上 last committed index,与 BookKeeper 中的 LastAddConfirmed 较为类似,只是 BK 是通过 Writer 来协调数据在不同节点的一致性,Raft 有 leader 来协调数据在不同节点的一致性。
BookKeeper 的 IO 读写分离
下图是每个数据节点的数据流转过程,数据写入时,Writer 通过 append only 方式写入到 Journal,Journal 在把数据写到内存的同时会按一定频率(默认 1ms 或 500 byte)把数据持久化到 Journal Device 里,写完后会告诉 Writer 这个节点写入成功了(持久化到磁盘是默认配置)。
Journal 在数据写入时有写到内存中,接下来在内存中做排序(用于解决如果按写的顺序读会导致分区随机性强的问题),然后把数据刷到数据盘中。读的时候,如果读最新的数据,可以直接从内存里返回,如果读历史数据,也只去读数据盘,不会对 Journal Device 写入有影响。这样针对有读瓶颈或写瓶颈的用户,可以把 Journal Disk 或 Ledger Disk 换成 SSD 盘,提升性能,并且防止读写的互相干扰。
BookKeeper 的存储介质演变
BookKeeper 的 Disk 演进
在演进过程中,因为顺序读的情况比较多,所以读的部分变化不大,但在写的这部分经历了 HDD 到 SSD 再到 NVMe SSD,再到现在部分用户换成了 Intel 的 PMem 的过程(如下图所示)。在换到 NVMe SSD 时,部分用户通过多目录的方式可以把 SSD 的 IO 带宽打的很满。
PMEM 在 BookKeeper 上的应用
PMem 的特性非常匹配 Journal Disk,单块 PMem 可以达到 3-4GB 的带宽,不但能提供高带宽吞吐而且可持久化。PMem 容量相比 SSD 比较小、相比内存又比较大,在刚推出时单条 128GB,有着 GB 级别的吞吐和 ns 级别的延迟。
高吞吐低容量的 PMem 非常适合 Journal 持久话刷盘的需求,例如宕机后,需要对没刷到磁盘的这部分数据做恢复,需要 Journal 做 replay log 重放,由于只是增量日志而非全量数据,所以并不需要很大的容量,正好和 PMem 容量不大相匹配。而且,PMem 的寿命会比 SSD 的寿命长一些,例如在每天同样写入量下 SSD 可能只能用 1 年而 PMem 预计可以使用 4-5 年。
雅虎(现在是 Verizon Media)有实际通过 PMEem 优化 BookKeeper 的案例,在只增加 5%的单机成本情况下提升了 5 倍的带宽吞吐和低于 5ms 的时延保障(BookKeeper 社区与 Intel 正在合作做性能测试,预计未来会产出白皮书说明)。
在雅虎案例中用 10 台 Pulsar(底层是用 PMem 做 Journal Disk 的 BookKeeper)替换了 33 台 Kafka,比原 Kafka 方案成本降低了一半,产出的对比结果如下:
社区资源
团队构成
由 Apache Pulsar 核心研发团队创立,同时有 Apache Pulsar 和 Apache BookKeeper 项目管理委员会(PMC)主席,有 6 名 Apache Pulsar PMC 成员和 3 名 Apache BookKeeper PMC 成员,有约 20 名 Apache Committer。
里程碑
公司成立于 2019 年,2020 年发布商业化产品 StreamNative Cloud,目前有 50+付费客户,覆盖金融、IoT、互联网、制造多个行业。
优势
是社区和代码的构建维护者,有全球最专业的 Pulsar 设计开发、运维、管理团队的 7*24 小时服务,提供开箱即用的云服务和咨询培训服务。
相关阅读
▼ 关注「Apache Pulsar」获取更多技术干货 ▼
点击阅读原文,立即观看回顾视频!
本文分享自微信公众号 - ApachePulsar(ApachePulsar)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。