组队大项目--消息队列篇 pulsar | 青训营笔记

111 阅读4分钟

这是我参与「第五届青训营 」笔记创作活动的第2天 本次大项目选择了pulsar作为消息队列的技术选型。

Apache® Pulsar™ 是一个为云构建的开源的分布式消息传递和流式平台。 在架构设计上和之前大热的rabbitMQ和Kafka有着显著区别

Pulsar亮点

首先RabbitMQ和Kafka的消息都是存储在Broker的磁盘或内存中。 客户端在访问某个topic的partition之前,首先要找到这个partition所在的Broker,然后连接到这个Broker上进行produce和consume。

在cluster模式下,为了避免single point of failure的情况造成消息丢失,Broker在保存消息的时候,必须把消息复制到其他的Broker上。当某个Broker节点故障的时候, 并不是集群中任意一个节点都能替代发生这个故障的节点,只有那些“和这个故障节点拥有相同数据的节点”才能替代这个故障的节点。 原因就是每个Broker存储的消息数据是不同的。这种节点称为“有状态的节点(Stateful Node)"。

Pulsar和其他消息队列在架构上最大的区别就是,它的Broker是无状态的(Stateless)。即在Pulsar的Broker既不保存元数据,也不存储消息。 Pulsar的架构图如下(来自官网pulsar.apache.org/docs/2.11.x… )

image.png

先看图中右侧的Bookie和ZK。ZK是ZooKeeper cluster,用于存储元数据。BookKeeper集群则被用来存储消息数据。

BookKeeper的存储单元是Ledger。 Ledger是一段WAL(Write Ahead Log), 它包含了连续的若干条消息,消息在Ledger中称为Entry。 为了保证Ledger中的Entry的严格顺序, Pulsar为Ledger增加了一次性的写入限制, Broker创建一个Ledger后, 只有这个Broker可以往Ledger中写入Entry。一旦Ledger关闭后,无论是主动还是异常原因关闭,这个Ledger都只能读取不能写入了。如果需要继续写入Entry,只能新建另外一个Ledger。

Ledger这个资源不共享,也就不需要加锁,解决了并发写入控制的问题,

综上,Pulsar的Broker不需要存储任何数据了,这个Broker也就成为了无状态的节点。但是在一个特定的时刻,每个Topic的partition还是要落在某个具体的Broker上。 不能说多个Broker同时读写同一个partition,这样就没法保证消息的顺序,也就没法来管理消费位置。

再来看图中左侧最大的那个Broker,在 Broker 中包含了几个重要的模块。Load Balancer 负责动态的分配,即哪些 Broker 管理哪些Topic的partition。Managed Ledger 这个模块负责管理本节点需要用到的那些 Ledger,当然这些 Ledger 都是保存在 BookKeeper 集群中的。为了提升性能,Pulsar 同样采用用了一个 Cache 模块,来缓存一部分 Ledger。

Pulsar的Client要读写某个Topic的partition上的数据之前,依然要在metadata中找到分区当前所在的那个 Broker,这一点是和其他消息队列的实现是一样的。不一样的地方是,其他的消息队列,分区与 Broker 的对应关系是相对稳定的,只要不发生故障,这个关系是不会变的。而在 Pulsar 中,这个对应关系是动态的,它可以根据 Broker 的负载情况进行动态调整,而且由于 Broker 是无状态的,partition可以调整到集群中任意一个 Broker 上,这个负载均衡策略就可以做得非常简单并且灵活。如果某一个 Broker 发生故障,可以立即用任何一个Broker 来替代它。

那在这种架构下,Pulsar 又是如何来完成消息收发的呢?Client在收发消息之前,需要先 连接 Service Discovery 模块,获取当前Topic的partition与 Broker 的对应关系,然后再连接到相应 Broker 上进行消息收发。客户端收发消息的整体流程,和其他的消息队列是差不多的。比较显著的一个区别就是,消息是保存在 BookKeeper 集群中的,而不是本机上。数据的可靠性保证也是 BookKeeper 集群提供的,所以 Broker 就不需要再往其他的 Broker 上复制消息了。 图中的 Global replicators 模块虽然也会复制消息,但是复制的目的是为了在不同的集群 之间共享数据,而不是为了保证数据的可靠性。集群间数据复制是 Pulsar 提供的一个特色功能,具体可以看一下 Pulsar 文档中的geo-replication这部分。