一、前言
Pulsar是一个多租户,高性能的服务间音讯解决方案。最后由Yahoo开发,当初由Apache Software Foundation负责。
Pulsar是音讯队列畛域的一匹黑马,其最大长处在于它提供了比Apache Kafka更简单明了、更强壮的一系列操作性能,反对地区复制和多租户。此外,相比传统的Kafka、RocketMQ等,Pulsar更加适宜IoT的场景。
二、架构设计
2.1 整体架构
Apache Pulsar 和其余音讯零碎最基本的不同是采纳分层架构。
Apache Pulsar 集群由两层组成:
无状态服务层:由一组接管和传递音讯的Broker组成
有状态长久层:由一组Apache BookKeeper存储节点组成,可长久化地存储音讯。
Pulsar客户端不间接与存储层Apache BookKeeper交互。客户端也没有间接的 BookKeeper 拜访权限。这种隔离,为 Pulsar 实现平安的多租户对立身份验证模型提供了根底。
2.2 Broker
Broker集群在Apache Pulsar中造成无状态服务层。Broker不在本地存储任何音讯数据。Pulsar主题的音讯,都被存储在分布式日志存储系统(Apache BookKeeper)中。
每个主题分区(Topic Partition)由Pulsar调配给某个Broker,该Broker称为该主题分区的所有者。Pulsar 生产者和消费者连贯到主题分区的所有者 Broker,以向所有者代理发送音讯并生产音讯。
如果一个Broker产生故障,Pulsar会主动将其领有的主题分区挪动到群集中残余的某一个可用 Broker 中。重点阐明:因为Broker是无状态的,因而当产生Topic 的迁徙时,Pulsar 只是将所有权从一个 Broker 转移到另一个 Broker,并不会有任何数据复制产生,故障转移十分轻量。
下图显示了一个领有 4 个 Broker 的 Pulsar 集群,其中 4 个主题分区散布在 4 个 Broker 中。每个 Broker 领有并为一个主题分区提供音讯服务。
2.3 Bookeeper
Apache BookKeeper 是 Apache Pulsar 的长久化存储层。Apache Pulsar 中的每个主题分区实质上都是存储在 Apache BookKeeper 中的分布式日志。
每个分布式日志又被分为Segment分段。每个Segment分段作为Apache BookKeeper中的一个 Ledger,均匀分布并存储在BookKeeper群集中的多个Bookie中。
通过 Segment 分段的形式,主题分区中的音讯能够平均和均衡地散布在群集中的所有 Bookie 中。这意味着主题分区的大小不仅受一个节点容量的限度;相同,它能够扩大到整个 BookKeeper 集群的总容量。
上面的图阐明了一个分为 x 个 Segment 段的主题分区。每个 Segment 段存储 3 个正本。所有 Segment 都散布并存储在 4 个 Bookie 中。
2.4 劣势
计算存储拆散的个性给Pulsar带来了许多个性
无限度的主题分区存储
无缝Broker故障复原
无缝Bookeeper故障复原
无缝集群扩大
- 无限度的主题分区存储
因为主题分区被宰割成 Segment 并在 Apache BookKeeper 中以分布式形式存储,因而主题分区的容量不受任何繁多节点容量的限度。
主题分区能够扩大到整个 BookKeeper 集群的总容量,只需增加 Bookie 节点即可扩大集群容量。
这是 Apache Pulsar 反对存储有限大小的流数据,并可能以高效,分布式形式解决数据的要害。 - 无缝Broker故障复原
下图阐明了Broker故障复原。本例中Broker2因某种原因(例如停电)而断开。Pulsar检测到Broker2已敞开,并立刻将 Topic1-Part2的所有权从Broker2转移到Broker3。在Pulsar中数据存储和数据服务拆散,所以当代理3接管 Topic1-Part2的所有权时,它不须要复制Partiton的数据。如果有新数据到来,它立刻附加并存储为Topic1-Part2中的 Segment x + 1。Segment x + 1被散发并存储在Bookie1, 2和4 上。因为它不须要从新复制数据,所以所有权转移立刻产生而不会就义主题分区的可用性。 - 无缝Bookeeper故障复原
下图阐明了Bookeeper的故障复原。这里有一个磁盘故障导致存储在 bookie2 上的Segment 4 被毁坏。Apache BookKeeper 后盾会检测到这个谬误并进行复制修复。
BookKeeper中的正本修复是 Segment级别的多对多疾速修复,这比从新复制整个主题分区要精密,只有复制必须的数据。这意味着Apache BookKeeper 能够从bookie3和bookie4读取Segment4中的音讯,并在bookie1处修复Segment4。所有的正本修复都在后盾进行,对 Broker和利用通明。
即便有Bookie节点出错的状况产生时,通过增加新的可用的Bookie来替换失败的Bookie,所有Broker 都能够持续承受写入,而不会就义主题分区的可用性。
- 无缝集群扩大
下图阐明了Pulsar集群扩大。当Broker2将音讯写入Topic1-Part2的Segment X时,将Bookie X和 Bookie Y增加到集群中。Broker2立刻发现新退出的Bookies X和Y。而后Broker将尝试将Segment X + 1和X + 2 的音讯存储到新增加的Bookie中。新减少的Bookie立即被应用起来,流量立刻减少,而不会从新复制任何数据。除了机架感知和区域感知策略之外,BookKeeper还提供资源感知的搁置策略,以确保流量在群集中的所有存储节点之间保持平衡。
三、音讯模型
3.1 通用的音讯模型
音讯模型个别以下 3 个方面:
- 音讯生产:如何发送和生产音讯
- 音讯确认(ACK):如何确认音讯
- 音讯保留(Retention):音讯保留工夫,触发音讯删除的起因以及怎么删除
3.2 通用的生产模型
队列模型
队列模型次要是采纳无序或者共享的形式来生产音讯。
通过队列模型,多个消费者能够从单个管道中接管音讯;当一条音讯从队列发送进去后,多个消费者中的只有一个(任何一个都有可能)接管和生产这条音讯。音讯零碎的具体实现决定了最终哪个消费者理论接管到音讯。
队列模型通常与无状态应用程序一起联合应用。无状态应用程序不关怀排序,但它们的确须要可能确认(ack)或删除单条音讯,以及尽可能地扩大生产并行性的能力。典型的基于队列模型的音讯零碎包含 RabbitMQ 和 RocketMQ。
流模型
流模型要求音讯的生产严格排序或独占音讯生产。
对于一个管道,应用流式模型,始终只会有一个消费者应用和生产音讯。消费者依照音讯写入管道的确切程序接管从管道发送的音讯。
流模型通常与有状态应用程序相关联。有状态的应用程序更加关注音讯的程序及其状态。音讯的生产程序决定了有状态应用程序的状态。音讯的程序将影响利用程序处理逻辑的正确性。
3.3 Pulsar音讯生产
Pulsar形象出了对立的生产模型: producer-topic-subscription-consumerPulsar的音讯模型既反对队列模型,也反对流模型
Topic是用于发送音讯的通道。Topic中的每条音讯,能够依据消费者的订阅需要,屡次被应用,每个订阅对应一个消费者组(Consumer Group)。每个Topic能够有不同的生产组。
消费者(consumer)被组合在一起以生产音讯,每个生产组是一个订阅(subscription)
消费者能够领有不同的生产形式:独占(Exclusive),故障切换(Failover)或共享(Share)
Pulsar通过这种模型,将队列模型和流模型这两种模型联合在了一起,提供了对立的API接口。这种模型,既不会影响音讯零碎的性能,也不会带来额定的开销,同时还为用户提供了更多灵活性,不便用户依据本人的理论场景来应用音讯零碎。
独占订阅(流模型)
独占模式,topic只能被一个消费者订阅。如果多于一个消费者以同样形式去订阅主题,消费者将会收到谬误。
下图中,只有Consumer A-0能够生产
容灾订阅(流模型)
容灾模式,多个消费者能够订阅同一个topic,消费者按音讯者名称的字典序排列。第一个消费者被初始化为惟一接管音讯的消费者。这个消费者被称为主消费者(master consumer)。
当主消费者断开时,所有的音讯(未被确认和后续进入的)将会被分发给下一个消费者。
在下图中,Consumer-B-0是主消费者,如果Consumer-B-0断开连接,Consumer-B-1会变成主消费者去接管音讯
共享订阅(队列模型)
在共享(shared)或轮询(round robin)模式下,多个使用者能够订阅同一个topic。音讯通过轮询形式分发给不同的消费者,并且每个音讯仅会被分发给一个消费者。
当消费者断开连接,所有被发送给它,但没有被确认的音讯将被重新安排,分发给其它存活的消费者。在下图中,Consumer-C-1和Consumer-C-2能够订阅该主题,然而Consumer-C-3和其余消费者也能够订阅该主题。
3.4 Pulsar音讯确认
当应用分布式音讯零碎时,可能会产生故障。比方在消费者从音讯零碎中的主题生产音讯的过程中,消费者和Broker都可能产生谬误。音讯确认(ACK)的目标就是保障当产生这样的故障后,消费者可能从上一次进行的中央复原生产,保障既不会失落音讯,也不会反复解决曾经ACK的音讯。
在 Pulsar 中,每个订阅中都应用一个专门的数据结构——游标(Cursor)来跟踪订阅中的每条音讯的ACK状态。每当消费者确认音讯时,游标都会更新。更新游标可确保消费者不会再次收到音讯。
Pulsar 提供两种音讯确认办法,单条确认(Individual Ack)和累积确认(Cumulative Ack)。通过累积确认,消费者只须要确认它收到的最初一条音讯。主题分区中的所有音讯(包含)提供音讯 ID 将被标记为已确认,并且不会再次传递给消费者。
Pulsar 能够反对音讯的单条确认,也就是选择性确认。消费者能够独自确认一条音讯。被确认后的音讯将不会被从新传递。下图阐明了单条确认和累积确认的差别(灰色框中的音讯被确认并且不会被从新传递)。在图的上半局部,它显示了累计确认的一个例子,M12 之前的音讯被标记为 acked。在图的下半局部,它显示了独自进行 acking 的示例。仅确认音讯 M7 和 M12 - 在消费者失败的状况下,除了 M7 和 M12 之外,其余所有音讯将被从新传送。
独占订阅或容灾订阅的消费者可能对音讯进行单条确认和累积确认;共享订阅的消费者只容许对音讯进行单条确认。单条确认音讯的能力为解决消费者故障提供了更好的体验。对于某些利用来说,解决一条音讯可能须要很长时间或者十分低廉,避免从新传送曾经确认的音讯十分重要。
游标(Cursor)由 Broker 来治理,利用 BookKeeper 的 Ledger 提供存储。
Apache Pulsar 提供了灵便的音讯生产订阅类型和音讯确认办法,通过简略的对立的 API,就能够反对各种音讯和流的应用场景。
3.5 Pulsar音讯保留
在音讯被确认后,Pulsar 的 Broker 会更新对应的游标。当 Topic 外面中的一条音讯,被所有的订阅都确认 ack 后,能力删除这条音讯。Pulsar 还容许通过设置保留工夫,将音讯保留更长时间,即便所有订阅曾经确认生产了它们。
下图阐明了如何在有 2 个订阅的主题中保留音讯。订阅 A 在 M6 和订阅 B 曾经耗费了 M10 之前的所有音讯之前曾经耗费了所有音讯。这意味着 M6 之前的所有音讯(灰色框中)都能够平安删除。订阅 A 仍未应用 M6 和 M9 之间的音讯,无奈删除它们。如果主题配置了音讯保留期,则音讯 M0 到 M5 将在配置的时间段内放弃不变,即便 A 和 B 曾经确认生产了它们。
在音讯保留策略中,Pulsar 还反对音讯生存工夫(TTL)。如果音讯未在配置的 TTL 时间段内被任何消费者应用,则音讯将主动标记为已确认。音讯保留期音讯 TTL 之间的区别在于:音讯保留期作用于标记为已确认并设置为已删除的音讯,而 TTL 作用于未 ack 的音讯。下面的图例中阐明了 Pulsar 中的 TTL。例如,如果订阅 B 没有流动消费者,则在配置的 TTL 时间段过后,音讯 M10 将主动标记为已确认,即便没有消费者理论读取该音讯。
四、为什么Pulsar更适宜IoT场景
4.1 海量Topic
Pulsar计算存储拆散的架构,使得Pulsar能够反对百万级别Topic数量的扩大,同时还能始终保持良好的性能。
Topic的伸缩性取决于它的外部组织和存储形式。Pulsar的数据保留在BookKeeper 服务器上,处于写状态的不同 Topic的音讯,在内存中排序,最终聚合保留到大文件中,在Bookie中须要更少的文件句柄。另一方面Bookie的 IO 更少依赖于文件系统的Pagecache,Pulsar 也因而可能反对大量的主题。
这是一个极大的晋升,相比之下,Kafka计算存储未分离,Topic多了之后会影响其程序IO,性能会呈现比较严重的降落。
IoT场景的Topic数量是数以亿计的,Pulsar能反对海量Topic的能力恰好满足了IoT场景的需要
4.2 租户隔离
Pulsar 通过租户和命名空间这两个要害概念反对多租户,Pulsar 的多租户性质次要体现在 topic 的 URL 中
{persistent|non-persistent}://tenant/namespace/topic
多租户是IoT场景的一个根本需要,Pulsar通过在topic中附加命名空间达到了租户隔离的成果。
4.3 音讯TTL
Pulsar能够给未被确认的音讯设置存活时长(TTL),尽管TTL的设置是针对整个namespace起效的,无奈针对单个 Topic,但能够满足IoT场景下不同用户个性化指定TTL的要求
五、参考文献
https://streaml.io/blog/pulsa...
https://pulsar.apache.org/zh-CN/
物联网平台产品介绍详情:https://www.aliyun.com/produc...
阿里云物联网平台客户交换群