比较Apache Pulsar 和Apache Kafka:统一排队和流式传输 - splunk


消息传递模型是用户在选择流式消息传递系统时应该考虑的第一件事。消息传递模型应涵盖以下 3 个方面:

  • 消息消费 - 消息是如何发送和消费的?
  • 消息确认 - 如何确认消息?
  • 邮件保留 - 邮件保留多长时间、触发删除的原因以及如何删除?

  
消息消费
在现代实时流式架构中,消息传递用例可以分为两类:排队和流式传输。
排队
排队 是无序或 共享的 消息传递。使用队列消息传递,创建多个消费者以从单个点对点消息传递通道接收消息。当通道传递消息时,任何消费者都可能收到它。消息系统的实现决定了哪个消费者实际接收到消息。
排队用例通常与无状态应用程序结合使用。无状态应用程序不关心排序,但它们 确实 需要能够确认或删除单个消息以及尽可能扩展消费并行性的能力。典型的基于队列的消息系统包括 RabbitMQ 和 RocketMQ。
流媒体
相比之下, 流媒体 是严格有序或 排他的 消息传递。使用流式消息传递,始终只有一个消费者在使用消息传递通道。消费者按照写入的确切顺序接收从通道发送的消息。
流用例通常与有状态的应用程序相关联。有状态的应用程序关心排序及其状态。消息的顺序决定了有状态应用程序的状态。当发生乱序消费时,排序将影响应用程序需要应用的任何处理逻辑的正确性。
 在面向微服务或事件驱动的架构中,流式传输 排队都是必需的。
 
Apache Pulsar模型
Apache Pulsar 将排队和流式统一到一个统一的消息模型中:  producer-topic-subscription-consumer。主题(分区)是用于发送消息的命名通道。每个主题分区都由存储在 Apache BookKeeper中的分布式日志支持。发布者发布的每条消息仅在主题分区上存储一次,然后复制以存储在多个 bookie(BookKeeper 服务器)上,并且消费者可以根据需要多次使用。
话题Topic是消费的真相源泉。尽管消息在主题分区上只存储一次,但可以有不同的方式来使用这些消息。消费者被组合在一起以消费消息。每组消费者都是一个主题的订阅。每个消费者组都可以有自己的消息消费方式——独占、共享或故障转移——这在不同的消费者组之间可能不同。这将队列和流式处理结合在一个模型和 API 中,其设计和实现的目标是不影响性能和引入成本开销,同时还为用户提供了很大的灵活性,以最适合用例的方式消费消息在眼前。
  • 独家订阅(流媒体)

顾名思义,订阅(消费者组)中只能有一个消费者在任何给定时间使用主题分区。
  • 故障转移订阅(流)

使用故障转移订阅,多个消费者可以附加到同一个订阅。然而,对于给定的主题分区,一个消费者将被选为该主题分区的主消费者。其他消费者将被指定为故障转移消费者。当主消费者断开连接时,分区将被重新分配给故障转移消费者之一进行消费,而新分配的消费者将成为新的主消费者。
  • 共享订阅(排队)

使用共享订阅,您可以将任意数量的消费者附加到同一个订阅。消息在多个消费者之间以循环分发的方式传递,任何给定的消息都只传递给一个消费者。当消费者断​​开连接时,所有传递给它但未确认的消息将被重新安排发送给在该订阅上存活的剩余消费者。
 
独占订阅和故障转移订阅仅允许每个订阅的每个主题分区有一个使用者。他们按分区顺序消费消息。它们最适用于需要严格排序的流用例。另一方面,共享订阅允许每个主题分区有多个消费者。同一订阅中的每个消费者只接收发布到主题分区的部分消息。共享订阅最适合不需要排序的排队用例,并且可以将消费者数量扩展到分区数量之外。
Pulsar 中的订阅实际上与 Apache Kafka 中的消费者组相同。创建订阅具有高度可扩展性且非常便宜。您可以根据需要创建任意数量的订阅。同一主题的不同订阅不必属于相同的订阅类型。这意味着您可以在同一主题上拥有一个包含 10 个使用者的故障转移订阅和一个包含 20 个使用者的共享订阅。如果共享订阅处理事件很慢,可以在不改变分区数量的情况下,向共享订阅添加更多消费者。
除了统一消息 API 之外,由于 Pulsar 主题分区实际上是存储在 Apache BookKeeper 中的分布式日志,因此它还提供了一个阅读器 API(类似于消费者 API,但没有游标管理)供用户完全控制如何自己消费消息。
 
消息确认
使用跨机器分布的消息传递系统时,可能会发生故障。在消费者从消息系统中的主题消费消息的情况下,消费消息的消费者和为主题分区提供服务的消息代理都可能失败。当发生此类故障时,一旦一切恢复,能够从消费者停止的地方恢复消费是很有用的,这样您就不会错过消息,也因此您不必处理已经确认的消息. 恢复点在 Apache Kafka 中通常称为偏移量,更新恢复点的过程称为消息确认,或提交偏移量。
在 Apache Pulsar 中,游标用于跟踪每个订阅的消息确认。每当消费者在主题分区上确认消息时,都会更新游标。更新游标确保消费者不会再次收到消息。然而,游标并不是 Apache Kafka 中的简单偏移量。光标更多。
Apache Pulsar 有两种方式来确认消息,单独确认或累积确认。通过累积确认,消费者只需要确认它收到的最后一条消息。主题分区中直到(包括)提供消息 id 的所有消息都将被标记为已确认,并且不会再次重新传递给消费者。累积确认实际上与 Apache Kafka 中的偏移量更新相同。
Apache Pulsar 的不同之处在于能够单独确认,也就是选择性确认。消费者能够单独确认消息。确认的消息将不会被重新传递。图 5 说明了 ack 个人和 ack 累积之间的区别(灰色框中的消息被确认并且不会被重新传递)。在图的顶部,它显示了 ack 累积的示例,M12 之前(和包括)的消息被标记为 acked。在图的底部,它显示了单独响应的示例。只有消息 M7 和 M12 被确认 - 在消费者失败的情况下,所有消息都将被重新传递,除了 M7 和 M12。
独占或故障转移订阅中的消费者能够单独或累积地确认消息;而共享订阅中的消费者只允许单独确认消息。单独确认消息的能力为处理消费者故障提供了更好的体验。对于某些应用程序来说,防止重新传递已经确认的消息非常重要,因为对于那些应用程序来说,处理消息可能需要很长时间或者非常昂贵。
选择订阅类型和确认方法的灵活性允许 Pulsar 在一个简单的统一 API 中支持各种消息传递和流式处理用例。
 
消息保留
与传统的消息传递系统相比,消息在被确认后不会立即被删除。Pulsar brokers 仅在收到消息确认时更新光标。只有在所有订阅都已经使用它之后才能删除消息(消息在其游标中标记为已确认)。但是,Pulsar 还允许您将消息保留更长时间,即使在所有订阅都已经使用它们之后。这是通过配置消息保留期来完成的。
 
下表列出了 Apache Pulsar 和 Apache Kafka 的异同:
  • Kafka

更专注于流式传输,分区上的独家消息传递。没有共享消费。
简单的偏移管理
  1. 在 Kafka 0.8 之前,偏移量存储在 ZooKeeper 中
  2. 在 Kafka 0.8 之后,偏移量存储在偏移量主题上

根据保留删除消息。如果消费者在保留期之前没有阅读消息,它将丢失数据。
不支持 TTL。
  • Pulsar

统一的消息传递模型和 API。
  1. 通过独占的故障转移订阅流式传输
  2. 通过共享订阅排队

消息仅在所有订阅都使用它们后才会被删除。即使订阅的消费者长时间停机,也不会丢失数据。即使在所有订阅都使用它们之后,也允许消息保留配置的保留期。
支持消息TTL。

Apache Pulsar 将高性能流(Apache Kafka 追求)和灵活的传统队列(RabbitMQ 追求)结合到一个统一的消息传递模型和 API 中。Pulsar 使用统一的 API 为您提供了 一个 用于流式处理和排队的系统,具有相同的高性能。