组队大项目--消息队列篇 pulsar续 --pulsar和kafka差异 第二篇 | 青训营笔记

51 阅读5分钟

这是我参与「第五届青训营 」笔记创作活动的第4天

Schema

在 Kafka 生态中,可以通过 Confluent Schema 注册表以及生产者/消费者 SerDes 来实现对消息的 Schema 验证。应用程序开发人员可以对客户端进行配置,让客户端与注册表服务集成并能够发现和发布其 Schema。通过适当的配置,客户端可以对发布的消息进行验证。

Pulsar 也有类似的功能,即服务器端 Schema 策略。但请注意,“服务器端”这个提法意味着 Schema 注册表功能是与 Pulsar Broker 集成的,而不是解耦的第三方服务。如此一来,这种集成会直接体现在 Pulsar 客户端 API 中,因此不需要额外配置 Schema 注册表端点(Endpoint)、SerDes 以及主题命名策略(Subject Name Strategy)。Pulsar 支持与 Kafka 相同的 Schema 类型(Avro、Protobuf 等)以及演化保证。

    Producer<User> producer = client.newProducer(JSONSchema.of(User.class))
       .topic(topic)
       .create();
User user = new User("Bob", 23);
producer.send(user);

生产者

多个生产者可以同时连接到 Kafka 主题并向其发送消息。Pulsar 也提供这种主题访问语义,使用默认的 Shared 生产者访问模式即可。因此,可以预期对于大多数使用场景,我们不需要额外的操作即可达到同样的效果。请注意,虽然单个 Kafka 生产者实例可以写入多个主题,但 Pulsar 的习惯做法是每个主题一个生产者实例。

分区

分区是生产者在主题的各个分区之间分发消息的过程。在 Kafka 中,我们可以通过在每个消息上设置一个 key 并为生产客户端提供一个分区器来控制消息分发。Pulsar 采用了非常类似的方法,但其术语略有不同。在 Pulsar 中,我们也可以通过设置消息的 key 来指导分区,不过 Pulsar 的消息 key 必须是字符串类型,而 Kafka 则支持 byte[] 类型。另外,可以通过配置 Producer 客户端的 MessageRoutingMode 来进一步控制分区。Pulsar 的默认路由模式是 RoundRobinPartition,使用消息 key 的哈希值来将消息分配到分区,而 round-robin 模式可以分配没有 key 的消息。比较方便的一点是,这些分区语义与 Kafka 的默认分区器相同,因此可以预期对于大多数使用场景,我们不需要额外的操作即可达到同样的效果。此外,对于自定义行为,Pulsar 的路由模式提供了与 Kafka 分区器相同的灵活性。

副本

与 Kafka 一样,Apache Pulsar 可以为接收到的消息保存多个副本,实际上 Pulsar 在这方面还提供了一些有趣的灵活性。与 Kafka 不同的是,Pulsar 的消息存储与 Broker 分离,即不受存储位置的限制。在实践中这意味着我们可以独立地设置消息副本的数量和存储节点的数量。Kafka 分区副本的消息只能写入特定的节点,而 Pulsar 的消息则分布在一组 Bookie(又称“Ensemble”)上。Jack Vanlightly 在他的博客中生动地描述了这一点:“Kafka 主题就像一根根 Toblerone 巧克力棒……而 Pulsar 主题就像气体,可以自由膨胀充满可用的空间”。请看下面的例子,在 5 个节点的 Pulsar 和 Kafka 集群中保存消息 M1-M3,副本数量为 3。

image.png 讲到副本,就不得不提副本故障,这是 Kafka 的痛点之一。你可能会想如果失去一个 Bookie 会怎么样?对集群有什么影响?可以确定的是,这种情况下集群需要拷贝副本不足的数据,但与 Kafka 不同,Pulsar 的影响后果更小。重要的是我们可以继续写入新数据,并保持所需的持久性;这是因为 Pulsar 的分区存储是高度分布式的,而 Kafka 则需要完整地同步分区数据才行。

消息确认

Kafka 生产者发送消息时可能会被阻塞,直到收到最低数量的 ACK,这样可以确信所生产的消息已被成功持久化到一定数量的副本中。Pulsar 也是如此,但也有一些差异。在 Kafka 中,生产者需要告诉 Broker 它需要多少个 ACK。因此,同一主题的不同生产者可能会向 Broker 请求不同数量的 ACK。在 Pulsar 中,ACK 由负责持久化消息的 Bookie 请求,而不是 Broker。此外,ACK 的数量也不由生产者指定。相反,它在主题级别上指定,直到达到所需的 ACK 数量前,任何同步生产者都会被阻塞。

最小 ISR(In-Sync Replica)

在 Pulsar 中要想设置与 Kafka 等价的 ACK 值比较复杂,因为 Kafka 的 all ACK 设置、集群范围内的 min.insync.replicas 设置、以及 Kafka 主题的副本数量会相互影响。生产者的 all ACKs 设置引入了不确定性;实际的 ACK 数量取决于当时的 ISR 数量。Kafka 生产者实际得到的 ACK 数量将介于 min.insync.replicas 的值和请求的 ACK 数量之间。

消费者

订阅类型决定着主题消费者的行为。订阅独立于主题,多个消费者可同时应用不同的消费语义。Pulsar 消息可以被单条确认,也可以不按顺序确认,以支持不同的消息场景。

消费者组

我们可以通过使用特定的 Pulsar 订阅类型来实现类似 Kafka 消费者组的功能。具体来说,我们可以创建订阅类型为灾备(Failover)的持久化(Durable)订阅。持久性可以确保确认被持久化(很像 Kafka 的偏移量管理);Pulsar 中的订阅默认是持久化的。灾备订阅类型确保只有一个消费者实例可以从分区中读取数据,消费者发生故障时,分区将会分配给另一个消费者实例。Pulsar 的默认订阅类型并不是灾备,因此必须明确指定。订阅一旦被创建,就必须由逻辑组中的所有消费者实例共享,分区将在这些实例之间进行分配。

消费顺序

在 Pulsar 中,灾备订阅类型确保任何时间都只有一个消费者可以从分区中读取数据,因此可以在分区范围内保证有序,这一点与 Kafka 一样。