乐趣区

关于后端:Message-deduplication-这里的去重与你想的可能不一样Apache-Pulsar-技术系列

导语

Apache Pulsar 是一个多租户、高性能的服务间音讯传输解决方案,反对多租户、低延时、读写拆散、跨地区复制、疾速扩容、灵便容错等个性。腾讯云外部 Pulsar 工作组对 Pulsar 做了深刻调研以及大量的性能和稳定性方面优化,目前曾经在腾讯外部业务 TDBank 落地上线。本文是 Pulsar 技术系列中的一篇,次要介绍 Pulsar 的 Message Deduplication 个性,供大家参考,防止在应用过程中踩坑。

Message Deduplication 背景介绍

消息中间件产品设计中,对音讯的投递设计,个别参照 Kafka 中提出的三种投递语意,别离为:
  至少一次 (at-most-once)
  至多一次 (at-least-once)
   准确一次(或恰好一次)(exactly-once)

了解上须要留神的是,这里都是对投递行为的限定形容。

至少一次:客户端在生产音讯的时候,仅会对生产的音讯投递一次,这里并不保障音讯肯定生产胜利。

至多一次:客户端在生产音讯的时候,在收到一次胜利的响应之前,可能会投递屡次。这种场景下,服务器端可能存在多条反复的音讯。

准确一次(或恰好一次):客户端在生产音讯的时候,针对这次生产,服务器端保障有且仅保留一份音讯。这里的“这次生产”,个别都是指的是客户端对一次“SendMessage”的调用。这种语意下,服务器个别不会解决屡次对雷同音讯体调用生产,产生反复音讯的场景。简略而言,就是“准确一次”并不等于音讯去反复。

许多零碎宣称提供“exactly-once”的交付语义,但仔细阅读其申明会发现,一些零碎的申明可能存在肯定的误导性,咱们须要思考它们在生产超时,局部正本写入胜利,局部失败等场景下对语意的保障。

目前业界,绝大多数的消息中间件产品,如 Kafka、RocketMQ、Pulsar、InLong-Tube、RabbitMQ、ActiveMQ 等,都反对 at-least-once(至多一次)的投递语意,即生产胜利的音讯,服务器端至多能保障存储一份,消费者至多能生产到一份音讯。然而,对 exactly-once(准确一次)语意反对的产品还是比拟少。

上面,咱们着重介绍一下 Pulsar 的 Message Deduplication(相当于对 exactly-once 的一种实现)性能,可能与你想的并不一样。

Pulsar 的音讯去重(Message deduplication)

性能配置

Pulsar 提供的 Message Deduplication 性能,默认是敞开的。开启时,须要批改 Broker 端的配置,另外客户端也须要增加少许的配置。(详情可参考 pulsar 的官网)

开启 Message Deduplictiaon 能力,首先,Broker 端须要变更如下配置:


#是否开启 message deduplication 性能
brokerDeduplicationEnabled#deduplication 性能下,生产者的数量限度
brokerDeduplicationMaxNumberOfProducers
#broker 端生成 deduplication 快照信息的距离
brokerDeduplicationEntriesInterval
#生产者断链后,broker 端 deduplication 信息保留的时长
brokerDeduplicationProducerInactivityTimeoutMinutes

其次,生产者客户端须要做如下变更:

  1、为生产者指定一个名称。
  2、配置音讯生产超时为 0(默认为 30s)。

代码示例如下:

PulsarClient pulsarClient = PulsarClient.builder()        
        .serviceUrl("pulsar://localhost:6650")        
        .build();
Producer producer = pulsarClient.newProducer()   
        .producerName("producer-1")      
        .topic("persistent://public/default/topic-1")        
        .sendTimeout(0, TimeUnit.SECONDS)        
        .create();

性能原理

客户端对每一个发送的音讯申请,都会采纳递增形式生成一个惟一的 Sequence ID 编号,这个信息会被搁置在 Message 的元数据中,传输到 Broker 端。同时,客户端 Producer 也会保护一个发送的 PendingMessages 队列,当收到 Broker 端返回的发送 Ack 信息后,将 PendingMessages 中雷同 Sequence ID 的信息移除,客户端认为发送的这个音讯生产胜利。

当 Broker 开启 Message Deduplication 性能后,Broker 对对每个收到的音讯申请进行是否反复的判断。

判断的逻辑如下:

1、Broker 端针对每个生产者,以生产者名字为 key,分以后接管到的和曾经解决实现的两个维度保留生产音讯的最大 Sequence ID 信息:

/* 以后曾经承受不了到的 */
ConcurrentOpenHashMap<String, Long> highestSequencedPushed
/* 以后曾经存储解决过的 */
ConcurrentOpenHashMap<String, Long> highestSequencedPersisted

2、Broker 端每收到一个生产 Message 的申请,会进行是否反复的判断,即收到的最新的 Sequence ID 是否大于 Broker 端保留的两维度下雷同 ProducerName 下的 Sequence ID,如果大于则不反复,如果小于或等于则音讯反复。音讯反复时,Broker 端会间接返回,不会持续走后续的存储解决流程。

由下面 Pulsar 的 Message Depulication feature 相干的配置和实现原理的介绍。可知,Pulsar Broker 端的 Message Depulication 性能,并不是对音讯体的去重,而是客户端在不配置超时工夫的前提下,Broker 端在肯定的工夫范畴内,对同一个生产者名称下的客户端投递的具备雷同 Sequence id 的音讯的惟一行保障。

总结

Kafka 在 0.11.0.0 版本之后,针对 Topic 之内和多个 Topic 之间两种场景下的 exactly-once 语意,别离提供了反对传递幂等性解决的选项和类事物音讯的解决形式进行保障。有趣味的同学能够参展 kafka 的源码和官网介绍。

Pulsar 的 Message Deduplication feature 与 Kafka 的单 Topic 下对 exaxtly-once 语意的保障在实现形式上相似,也能够认为是对 exaxtly-once 语意的一种实现。

这里须要着重留神的是,exaxtly-once 不等于音讯去重。在理论的开发中,生产和生产局部都有可能产生反复的音讯。

音讯的生产者,在收到明确的音讯生产胜利的确认之前,音讯在服务器端的存储状态是不确定的。

例如,在肯定工夫内,生产者没有收到生产的响应,抉择了重发,这时,服务器端就可能有两份甚至多份音讯的正本。

此外,生产局部在如下几个场景也有可能获取到反复推送的音讯:
  1、消费者重启时,曾经生产,然而 Broker 端未收到 Ack 或消费者没有触发 Ack;
  2、Broker 重启,因为消费者的 Ack 信息并不是实时保留的,Broker 重启后可能会有大量的曾经生产的音讯会被反复推送;
  3、生产出现异常,客户端应用 reconsumerLater 或 negativeAck 形式进行确认,这时 Broker 会从新推送音讯。

因而,大家在选用消息中间件的个性时,须要留神相干的场景和限度。防止因为反复音讯对业务产生不必要的影响。

one more thing

腾讯云基于 Apache Pulsar 自研的消息中间件 –TDMQ Pulsar 版,具备极好的云原生和 Serverless 个性,兼容 Pulsar 的各个组件与概念,具备计算存储拆散,灵便扩缩容的底层劣势。目前 TDMQ Pulsar 版已开始商业化,对 Pulsar 感兴趣的用户能够进入官网理解详情。

退出移动版