非持久topic
简介
默认情况下,Pulsar会将所有未确认的消息持久存储在多个BookKeeper bookies(存储节点)上。因此,持久性主题上的消息数据可以在 broker 重启和订阅者故障转移之后继续存在。
Pulsar也提供了非持久topic。非持久topic的消息不会被保存在硬盘上,只存活于内存中。当使用非持久topic分发时,杀掉Pulsar的broker或者关闭订阅者,此topic( non-persistent))上所有的瞬时消息都会丢失,意味着客户端可能会遇到消息缺失。
非持久性主题具有这种形式的名称(注意名称中的 non-persistent):
non-persistent://tenant/namespace/topic
如何使用非持久topic的更多信息,请参考Non-persistent messagingcookbook
在非持久性topic状态下,broker无需将其持久化到BookKeeper中,而会立即将消息传递给所有连接的订阅者。如果有一个订阅者断开连接,broker将无法重发这些瞬时消息,订阅者将永远也不能收到这些消息了。 去掉持久化存储的步骤,在某些情况下,使得非持久topic的消息比持久topic稍微变快。但是同时,Pulsar的一些核心优势也丧失掉了。
非持久topic,消息数据仅存活在内存。 如果broker挂掉或者因其他情况不能从内存取到,你的消息数据就可能丢失。除非你的项目一定需要他或者你有能力确保它一定不会各种原因丢失消息,不然并不推荐使用
默认非持久topic在broker上是开启的。 你可以通过broker的配置关闭。您可以通过pulsar admin topics命令管理非持久性主题。有关更多信息,请参阅pulsar admin。
性能
一般情况下非持久性消息传递比持久性消息传递要更快,因为broker不需要持久化消息,并在消息传递到连接的代理后会立即将ACK发送回生产者。非持久topic让producer有更低的发布延迟。
客户端API
Producer和consumer以连接持久topic同样的方式连接到非持久topic。重要的区别是,topic的名称必须以non-persistent开头。非持久性主题支持三种订阅模式:独占、共享、故障转移
下面是一个非持久topic的java consumer例子:
PulsarClient client = PulsarClient.builder()
.serviceUrl("pulsar://localhost:6650")
.build();
String npTopic = "non-persistent://public/default/my-topic";
String subscriptionName = "my-subscription-name";
Consumer<byte[]> consumer = client.newConsumer()
.topic(npTopic)
.subscriptionName(subscriptionName)
.subscribe();
这里还有一个非持久topic的java producer例子:
Producer<byte[]> producer = client.newProducer()
.topic(npTopic)
.create();
消息保留和过期
Pulsar broker默认如下:
- 立即删除consumer(消费者)已确认的所有消息
- 以消息backlog的形式,持久保存所有的未被确认消息
Pulsar有两个特性,让你可以覆盖上面的默认行为。
- 消息保留:使你能够保存已经被consumer(消费者)确认的消息
- 消息过期: 允许您为尚未确认的消息设置生存时间(TTL)
消息的过期和保留都是在同一命名空间内进行操作管理的,有关操作方法,请查阅消息的保留与过期
下图说明了这两种概念:

顶部显示了消息的保留功能,因为所有topics的保留策略规定都在命名空间中,所有某些消息即使已被确认,也会持久地存储在Pulsar中。没有被留存规则覆盖的消息将会被删除。如果没有保留策略,所有已确认的消息都将被删除。
图中下面的是消息过期,有些消息即使还没有被确认,也被删除掉了。因为根据设置在namespace上的TTL,他们已经过期了。(例如,TTL为5分钟,过了十分钟消息还没被确认)
消息去重
消息去重保证了一条消息只能在 Pulsar 服务端被持久化一次。 消息去重是一个 Pulsar 可选的特性,它能够阻止不必要的消息重复,它保证了即使消息被消费了多次,也只会被保存一次。
下图展示了开启和关闭消息去重的场景:

最上面的场景中,消息去重被关闭。 Producer发布消息1到一个topic,消息到达broker后,被持久化到BookKeeper。 然后producer又发送了消息1(可能因为某些重试逻辑),然后消息被接收后又持久化在BookKeeper,这意味着消息重复发生了。
在第二个场景中,producer发送了消息1,消息被broker接收然后持久化,和第一个场景是一样的。 当producer再次发送消息时,broker知道已经收到个消息1,所以不会再持久化消息1.
消息的去重设置也是在命名空间级别中管理的有关更多说明,请参阅消息重复数据消除手册。
生产者幂等
也可以保证生产者每条消息只生成一次从而达到去重,这种方法通常被称为生产者幂等性。这种方式的缺点是,把消息去重的工作推给了应用去做。 在 Pulsar 中,消息去重是在 broker上处理的,用户不需要去修改客户端的代码。 相反,你只需要通过修改配置就可以实现。 可以通过查看消息去重指南去了解更多详细信息。
去重和实际一次语义
消息去重,使 Pulsar 成为了流处理引擎(SPE)或者其他寻求 “仅仅一次” 语义的连接系统所需的理想消息系统。 如果消息系统没有提供自动去重能力,那么 SPE (流处理引擎) 或者其他连接系统就必须自己实现去重语义,这意味着需要应用去承担这部分的去重工作。 使用Pulsar,严格的顺序保证不会带来任何应用层面的代价。
你能够在这篇博客上获得更详细的信息。
消息延迟传递
简介
延时消息功能允许你能够过一段时间才能消费到这条消息,而不是消息发布后,就马上可以消费到。在这个机制中,一条信息被存储在BookKeeper中,DelayedDeliveryTracker在发布到broker后就在内存中维护时间索引(time->messageId),一旦特定的延迟时间过去,它就会被传递给消费者。
延迟消息传递仅在共享订阅模式下有效。在独占和故障转移订阅模式下,延迟消息会立即发送。
如下图所示,说明了延时消息的实现机制:

Broker 保存消息是不经过任何检查的。 当消费者消费一条消息时,如果这条消息是延时消息,那么这条消息会被加入到DelayedDeliveryTracker当中。 订阅检查机制会从DelayedDeliveryTracker获取到超时的消息,并交付给消费者。
Broker
默认情况下启用延迟消息传递。您可以在broker配置文件中更改它,如下所示:
# Whether to enable the delayed delivery for messages.
# If disabled, messages are immediately delivered and there is no tracking overhead.
delayedDeliveryEnabled=true
# Control the ticking time for the retry of delayed message delivery,
# affecting the accuracy of the delivery time compared to the scheduled time.
# Default is 1 second.
delayedDeliveryTickTimeMillis=1000
生产者(Producer)
下面是 Java 当中生产延时消息一个例子:
// message to be delivered at the configured delay interval
producer.newMessage().deliverAfter(3L, TimeUnit.Minute).value("Hello Pulsar!").send();

本文深入探讨了Apache Pulsar的非持久topic,介绍其特性和性能,强调消息的非持久性可能导致的数据丢失风险。此外,讨论了消息保留、过期、去重和生产者幂等性,解释了这些机制如何影响消息系统的可靠性和效率。最后,提到了消息延迟传递的功能及其在共享订阅模式下的应用。
494

被折叠的 条评论
为什么被折叠?



