前面几篇文章主要是介绍怎么将pulsar装起来、用起来。本文主要介绍pulsar的架构原理以及这些独特设计带来的优势。
单个 Pulsar 集群由以下三部分组成:
其实根据上面的介绍可以很清晰发现pulsar的分层结构。Pulsar采用“存储和服务分离”
的两层架构(这是Pulsar区别于其他MQ系统最重要的一点,也是所谓的“下一代消息系统”的核心)。
Pulsar客户端提供消费者和生产者的接口,但是客户端不与Apache Bookeeper交互,客户端也没有直接的 BookKeeper 访问权限。这种隔离为Pulsar实现安全的多租户统一身份验证模型提供了基础。下图能够体现其存储和服务分离的特点。本文的1.2和1.3节将详细介绍broker层和bookkeeper层的原理。
Broker 实际上并不在本地存储任何消息数据。每个主题分区(Topic Partition)由 Pulsar 分配给某个 Broker,该 Broker 称为该主题分区的所有者。 Pulsar 生产者和消费者连接到主题分区的所有者 Broker,以向所有者代理发送消息并消费消息。
Pulsar 的 broker 是一个无状态组件,主要负责运行另外的两个组件:
下图显示了一个拥有 4 个 Broker 的 Pulsar 集群,其中 4 个主题分区分布在 4 个 Broker 中。每个 Broker 拥有并为一个主题分区提供消息服务。
如果一个 Broker 失败,Pulsar 会自动将其拥有的主题分区移动到群集中剩余的某一个可用 Broker 中。这里要说的一件事是:由于 Broker 是无状态的,当发生 Topic 的迁移时,Pulsar 只是将所有权从一个 Broker 转移到另一个 Broker,在这个过程中,不会有任何数据复制发生。
Apache BookKeeper 是企业级存储系统,旨在保证高持久性、一致性与低延迟。自 2011 年起,BookKeeper 开始在 Apache ZooKeeper 下作为子项目孵化,并于 2015 年 1 月作为顶级项目成功问世。
BookKeeper有以下特点:
Apache BookKeeper 是 Apache Pulsar 的持久化存储层。 Apache Pulsar 中的每个主题分区本质上都是存储在 Apache BookKeeper 中的分布式日志。
bookis中存了啥数据?咋存的呢?这涉及到很多名词。
如图所示,一个topic实际上是一个Segment流(ledgers),通过这个设计所以Pulsar他并不是一个单纯的消息队列系统,他也可以代替流式系统,所以他也叫流原生平台,可以替代flink等系统。可以看见我们的topic/partition(Event Stream),由多个Segment存储组成,而每个Segment由entry组成,这个可以看作是我们每批发送的消息通常会看作是一个entry。这个Segment(在bookies中称为Ledger)可以看作是我们写入文件的一个基本维度,同一个Segment的数据会写在同一个文件上面,不同Segment将会是不同文件。
bookie又是咋读写这些文件的呢?首先介绍bookie的读写架构图:
其实跟一下这个流程,感觉与HBASE好相似呀:
写流程:
读流程:
这不是铁铁的hbase预写日志和readcache吗?这样设计的好处有:支持高效的读写
在kafka中当我们的topic变多了之后,由于kafka一个topic一个文件,就会导致我们的磁盘IO从顺序写变成随机写。在rocketMq中虽然将多个topic对应一个写入文件,让写入变成了顺序写,但是我们的读取很容易导致我们的pagecache被各种覆盖刷新,这对于我们的IO的影响是非常大的。所以pulsar在读写两个方面针对这些问题都做了很多优化:
- 写流程:顺序写 +pagecache。在写流程中我们的所有的文件都是独立磁盘,并且同步刷盘的只有Journal,Journal是顺序写一个journal-wal文件,顺序写效率非常高。ledger和index虽然都会存在多个文件,但是我们只会写入pagecache,异步刷盘,所以随机写不会影响我们的性能。
- 读流程:broker cache + bookie cache,在pulsar中对于追尾读(tailing read)非常友好基本不会走io,一般情况下我们的consumer是会立即去拿producer发送的消息的,所以这部分在持久化之后依然在broker中作为cache存在,当然就算broker没有cache(比如broker是新建的),我们的bookie也会在memtable中有自己的cache,通过多重cache减少读流程走io。
我们可以发现在最理想的情况下读写的io是完全隔离开来的,所以在Pulsar中能很容易就支持百万级topic,而在我们的kafka和rocketmq中这个是非常困难的。
相比kafka以partition为存储的基本对象,pulsar以Segment为中心进行存储的好处如下。这也能帮我们更好的理解pulsar的架构。
无限制的主题分区存储
由于主题分区被分割成 Segment 并在 Apache BookKeeper 中以分布式方式存储,因此主题分区的容量不受任何单一节点容量的限制。 相反,主题分区可以扩展到整个 BookKeeper 集群的总容量,只需添加 Bookie 节点即可扩展集群容量。 这是 Apache Pulsar 支持存储无限大小的流数据,并能够以高效,分布式方式处理数据的关键。 使用 Apache BookKeeper 的分布式日志存储,对于统一消息服务和存储至关重要。
即时扩展,无需数据迁移
由于消息服务和消息存储分为两层,因此将主题分区从一个 Broker 移动到另一个 Broker 几乎可以瞬时内完成,而无需任何数据重新平衡(将数据从一个节点重新复制到另一个节点)。 这一特性对于高可用的许多方面至关重要,例如集群扩展;对 Broker 和 Bookie 失败的快速应对。 我将使用例子在下文更详细地进行解释。
无缝 Broker 故障恢复
下图说明了 Pulsar 如何处理 Broker 失败的示例。 在例子中 Broker 2 因某种原因(例如停电)而断开。 Pulsar 检测到 Broker 2 已关闭,并立即将 Topic1-Part2 的所有权从 Broker 2 转移到 Broker 3。在 Pulsar 中数据存储和数据服务分离,所以当代理 3 接管 Topic1-Part2 的所有权时,它不需要复制 Partiton 的数据。 如果有新数据到来,它立即附加并存储为 Topic1-Part2 中的 Segment x + 1。 Segment x + 1 被分发并存储在 Bookie1, 2 和 4 上。因为它不需要重新复制数据,所以所有权转移立即发生而不会牺牲主题分区的可用性。
无缝集群容量扩展
下图说明了 Pulsar 如何处理集群的容量扩展。 当 Broker 2 将消息写入 Topic1-Part2 的 Segment X 时,将 Bookie X 和 Bookie Y 添加到集群中。 Broker 2 立即发现新加入的 Bookies X 和 Y。然后 Broker 将尝试将 Segment X + 1 和 X + 2 的消息存储到新添加的 Bookie 中。 新增加的 Bookie 立刻被使用起来,流量立即增加,而不会重新复制任何数据。 除了机架感知和区域感知策略之外,Apache BookKeeper 还提供资源感知的放置策略,以确保流量在群集中的所有存储节点之间保持平衡。
无缝的存储(Bookie)故障恢复
下图说明了 Pulsar(通过 Apache BookKeeper)如何处理 bookie 的磁盘故障。 这里有一个磁盘故障导致存储在 bookie 2 上的 Segment 4 被破坏。Apache BookKeeper 后台会检测到这个错误并进行复制修复。
Apache BookKeeper 中的副本修复是 Segment(甚至是 Entry)级别的多对多快速修复,这比重新复制整个主题分区要精细,只会复制必须的数据。 这意味着 Apache BookKeeper 可以从 bookie 3 和 bookie 4 读取 Segment 4 中的消息,并在 bookie 1 处修复 Segment 4。所有的副本修复都在后台进行,对 Broker 和应用透明。
即使有 Bookie 节点出错的情况发生时,通过添加新的可用的 Bookie 来替换失败的 Bookie,所有 Broker 都可以继续接受写入,而不会牺牲主题分区的可用性。
独立的可扩展性
由于消息服务层和持久存储层是分开的,因此 Apache Pulsar 可以独立地扩展存储层和服务层。这种独立的扩展,更具成本效益:
当您需要支持更多的消费者或生产者时,您可以简单地添加更多的 Broker。主题分区将立即在 Brokers 中做平衡迁移,一些主题分区的所有权立即转移到新的 Broker。
当您需要更多存储空间来将消息保存更长时间时,您只需添加更多 Bookie。通过智能资源感知和数据放置,流量将自动切换到新的 Bookie 中。 Apache Pulsar 中不会涉及到不必要的数据搬迁,不会将旧数据从现有存储节点重新复制到新存储节点。
上面的内容来源于一下blog,加上一点自己的总结。特此引用:
下一代消息队列pulsar到底是什么?
Apache Pulsar简介
比拼 Kafka, 大数据分析新秀 Pulsar 到底好在哪
聊聊pulsar:pulsar的核心概念与基础架构
pulsar架构与原理
所有的变化,都可能伴随着痛苦和弯路,开放的道路,也不会是阔野坦途,但大江大河,奔涌向前的趋势,不是任何险滩暗礁,能够阻挡的。道之所在,虽千万人吾往矣。