最近这个 Apache Pulsar 消息中间件非常的火,号称云原生时代的下一代消息中件,今天,就一起来看看它到底有多牛逼?
Apache Pulsar简介
Apache Pulsar是一个企业级的分布式消息系统,最初由Yahoo开发并在2016年开源,目前正在Apache基金会下孵化。Plusar已经在Yahoo的生产环境使用了三年多,主要服务于Mail、Finance、Sports、 Flickr、 the Gemini Ads platform、 Sherpa以及Yahoo的KV存储。 Pulsar之所以能够称为下一代消息队列,主要是因为以下特性:
- 线性扩展。能够丝滑的扩容到成百上千个节点(Kafka扩容需要占用很多系统资源在节点间拷贝数据,而Plusar完全不用)
- 高吞吐。已经在Yahoo的生产环境中经受了考验,每秒数百万消息
- 低延迟。在大规模的消息量下依然能够保持低延迟(< 5ms)
- 持久化机制。Plusar的持久化机制构建在Apache BookKeeper之上,提供了写与读之前的IO隔离
- 基于地理位置的复制。Plusar将多地域/可用区的复制作为首要特性支持。用户只需配置好可用区,消息就会被源源不断的复制到其他可用区。当某一个可用区挂掉或者发生网络分区,plusar会在之后不断的重试。
- 部署方式的多样化。既可以运行在裸机,也支持目前例如Docker、K8S的一些容器化方案以及不同的云厂商,同时在本地开发时也只需要一行命令即可启动整个环境。
- Topic支持多种消费模式:exclusive、shared、failover
架构
从最上层来看,一个Plusar单元由若干个集群组成,单元内的集群可以互相之前复制数据, plusar中通常有以下几种组件:
- Broker:负责处理Producer发来的消息并分发给消费者。通过一个全局的ZK集群来处理多种协作式任务,例如说基于地理位置的复制。并将消息存储到BookKeeper中,同时单个集群内也需要有一套ZK集群,来存储一些元数据。
- BookKeeper集群: 内部包含多个bookies,用于持久化消息。
- ZooKeeper集群
Broker
Pulsar 的 Server 端,用来处理 Producer 和 Consumer 的数据收发逻辑. 每个 Broker管理 topic 中的一些分区, 生产者和消费者连接到主题分区的所有者 Broker 发送消息或消费消息.plusar中的broker是一个无状态的节点,主要负责三件事情:
- 暴露REST接口用于执行管理员的命令以及topic所有者的查询等
- 一个用于节点间通讯的异步的TCP服务器,协议目前采用的是Google之前开源的Protocol Buffer
- 为了支持地域复制,broker会将自己 集群所在的消息发布到其他可用区。
BookKeeper
BookKeeper是一个可横向扩展的、错误容忍的、低延迟的分布式存储服务,BookKeeper中最基本的单位是记录,实际上就一个字节数组,而记录的数组称之为ledger,BK会将记录复制到多个bookies,存储ledger的节点叫做bookies,从而获得更高的可用性和错误容忍性。
Pulsar 中把每一个消息认为是存储在 Apache BookKeeper 中的分布式日志, 每个分布式日志又被分为多个 Segment 分段, 每个 Segment
分段在 Apache BookKeeper 中叫做一个 Ledger,并分散储在 BookKeeper 群集中的多个节点中.通过 Segment 分段的方式,主题分区中的消息可以均衡地分布在群集中的所有Bookie 中.并且所有的副本是对等的,客户端可以从任何一个 Bookie 的副本中读取消息. 数 据写入 Bookie 的一个基本过程:
我们知道Kafka在0.8版本之前是将消费进度存储到ZK中的,但是ZK本质上基于单个日志的中心服务,简单来讲,ZK的性能不会随着你增加更多的节点而线性增加,会只会相反减少,因为更多的节点意味着需要将日志同步到更多的节点,性能也会随之下降,因此QPS也会受单机性能影响,因此0.8版本之后就将消费进度存储到了Kafka的Topic中,而RocketMQ最初的版本也类似,有几种不同的实现例如ZK、数据库等,目前版本采用的是存储到本机文件系统中,而Plusar采用了和Kafka类似的思想,Plusar将消费进度也存储到了BK的ledger中。
Topic
发布订阅系统中最核心的概念是topic,简单来说,topic可以理解为一个管道,producer可以往这个管道丢消息,consumer可以从这个管道的另一端读取消息,但是这里可以有多个consumer同时从这个管道读取消息。
每个topic可以划分为多个分区,同一个topic下的不同分区所包含的消息都是不同的。每个消息在被添加到一个分区后都会分配一个唯一的offset,在同一个分区内消息是有序的,因此客户端可以根据比如说用户ID进行一个哈希取模从而使得整个用户的消息都发往整个分区,从而一定程度上避免race condition的问题。 通过分区,将大量的消息分散到不同的节点处理从而获得高吞吐。默认情况下,plusar的topic都是非分区的,但是支持通过cli或者接口创建一定分区数目的topic。
Pulsar 是支持多租户(tenant)的,租户下面又分了命名空间(namespace). 所以 topic 的创建格式是/tenant/namespance/topic. 为了兼容kafka等消息中间件. pulsar预置了默认的租户和命名空间: pulibc/default. 举个例子,假设部署了一个 Pulsar 集群来支持多个应用程序,那么每个 tenant 都可以代表一个团队,一个核心的功能,或者一个产品线;一个 tenant 下面可以包含多个 namespace,例如,每个应用程序为一个 namespace; 一个 namespace 可以包含多个 Topic,如下图:
Producer
生产者, 负责将消息发送给 Broker 节点, 发送消息的过程如下:
- 通过负载均衡策略,动态的给 producer 分配一个合适的 broker 节点, 每个 broker 节点维护这 topic 的一些分区
- broker 将消息并发的发送给 N 个 bookie,这个 N 是可以配置的。broker 持有 BookKeeper的客户端 writer,writer 收到写请求后,会并发的写入 N 个 bookie。
- bookie 写完消息后会给 broker 一个回复,broker 收到指定数量的确认消息后就会认为写 BookKeeper 成功。这个数量是可配置的, 越大写 BookKeeper 延迟越大,数据一致性越高。
Subscription
订阅, 决定了消息具体是如何被分发到消费者的,Plusar支持几种不同的消费模式: exclusive、shared、failover。图示如下:
- Shared(共享订阅模式): 所使用共享订阅,在同一个订阅背后可以有任意多的消费者。订阅中的所有消息以循环分发形式主动投递给订阅背后的多个消费者,并且一个消息仅传递给一个消费者。当消费者断开连接时,所有传递给它但是未被确认(ack)的消息将被重新分配和组织,以便发送给该订阅上剩余的剩余消费者。在这种模式下如果想提高消费的速度,用户不需要增加分区数量,只需要在同一个订阅中添加更多的消费者。下图是共享订阅的示例。 消费者 C-1,C-2 和 C-3 都在同一主题上消费消息。 每个消费者接收大约所有消息的 1/3。
- Key_shared(基于 Key 的共享模式): 结合了 FailOver 和 Shared 的优势, 数据按一定的key 策略轮询的方式分发到每一个消费者.这样既保证了有序性, 又可以很轻易的通过扩容consumer 来增加消费速率
- Failover(故障切换模式): 每使用故障切换订阅,多个消费者(Consumer)可以附加到同一订阅。 但是,一个订阅中的所有消费者,只会有一个消费者被选为该订阅的主消费者, 其他消费者将被指定为故障转移消费者。当主消费者断开连接时,分区将被重新分配给其中一个故障转移消费者,而新分配的消费者将成为新的主消费者。 发生这种情况时,所有未确认(ack)的消息都将传递给新的主消费者,类似于 kafka 的消费模式, 保证了消费的有序性.
- 下图是故障切换订阅的示例。 消费者 B-0 和 B-1 通过订阅 B 订阅消费消息。B-0是主消费者并接收所有消息。 B-1 是故障转移消费者,如果消费者 B-0 出现故障,它将接管消费.
- Exclusive(独占订阅模式):顾名思义,独占订阅中,在任何时间,一个消费者组(订阅)中有且只有一个消费者来消费 Topic 中的消息。下图是独占订阅的示例。在这个示例中有一个有订阅 A 的活跃消费者 A-0,消息 m0 到 m4 按顺序传送并由 A-0 消费。如果另一个消费者 A-1 想要附加到订阅 A,则是不被允许的.
总结
Pulsar作为下一代分布式消息队列,拥有非常多吸引人的特性,也弥补了一些其他竞品的短板,例如地域复制、多租户、扩展性、读写隔离等等.
标签:订阅,消费者,试试,分区,Kafka,topic,消息,2023,BookKeeper From: https://blog.51cto.com/u_16149027/6592118