导语

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感兴趣的用户可以进入官网了解详情。

Message deduplication 这里的去重与你想的可能不一样|Apache Pulsar 技术系列的更多相关文章

  1. ☕【难点攻克技术系列】「海量数据计算系列」如何使用BitMap在海量数据中对相应的进行去重、查找和排序

    BitMap(位图)的介绍 BitMap从字面的意思,很多人认为是位图,其实准确的来说,翻译成基于位的映射,其中数据库中有一种索引就叫做位图索引. 在具有性能优化的数据结构中,大家使用最多的就是has ...

  2. WPF MVVM UI分离之《交互与数据分离》 基础才是重中之重~delegate里的Invoke和BeginInvoke 将不确定变为确定系列~目录(“机器最能证明一切”) 爱上MVC3系列~全局异常处理与异常日志 基础才是重中之重~lock和monitor的区别 将不确定变成确定~我想监视我的对象,如果是某个值,就叫另一些方法自动运行 将不确定变成确定~LINQ DBML模型可以对

    WPF MVVM UI分离之<交互与数据分离>   在我们使用WPF过程中,不可避免并且超级喜欢使用MVVM框架. 那么,使用MVVM的出发点是视觉与业务逻辑分离,即UI与数据分离 诸如下 ...

  3. Scrapy框架——介绍、安装、命令行创建,启动、项目目录结构介绍、Spiders文件夹详解(包括去重规则)、Selectors解析页面、Items、pipelines(自定义pipeline)、下载中间件(Downloader Middleware)、爬虫中间件、信号

    一 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前Scrapy的用途十分广泛,可 ...

  4. JavaScript数组去重的四种方法

    今天,洗澡的想一个有趣的问题,使用js给数组去重,我想了四种方法,虽然今天的任务没有完成,5555: 不多说,po代码: //方法一:简单循环去重    Array.prototype.unique1 ...

  5. Lambda如何实现条件去重distinct List,如何实现条件分组groupBy List

    条件去重 我们知道, Java8 lambda自带的去重为 distinct 方法, 但是只能过滤整体对象, 不能实现对象里的某个值进行判定去重, 比如: List<Integer> nu ...

  6. Apache Spark 2.2.0 中文文档 - Structured Streaming 编程指南 | ApacheCN

    Structured Streaming 编程指南 概述 快速示例 Programming Model (编程模型) 基本概念 处理 Event-time 和延迟数据 容错语义 API 使用 Data ...

  7. [Pulsar系列] 10分钟学会Pulsar消息系统概念

    Apache Pulsar Pulsar是一个支持多租户的.高性能的服务与服务之间消息通讯的解决方案,最初由雅虎开发,现在由Apache软件基金会管理. Pulsar的主要特性如下: Pulsar实例 ...

  8. 97、爬虫框架scrapy

    本篇导航: 介绍与安装 命令行工具 项目结构以及爬虫应用简介 Spiders 其它介绍 爬取亚马逊商品信息   一.介绍与安装 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, ...

  9. python爬取youtube视频 多线程 非中文自动翻译

    声明:我写的所有文章都是发在博客园的,我看到其他复制粘贴过去的 连个出处也不写,直接打上自己的水印...真是没的说了. 前言:前段时间搞了一些爬视频的项目,代码都写好了,这里写文章那就在来重新分析一遍 ...

随机推荐

  1. 使用JSONArray.fromObject转化list时,如果有集合属性,很容易出错,此刻把集合属性过滤掉便可

    使用JSONArray.fromObject转化list时,如果有集合属性,很容易出错,此刻把集合属性过滤掉便可

  2. Hive实战—时间滑动窗口计算

    关注公众号:大数据技术派,回复: 资料,领取1024G资料. 目录 时间滑动计算 外部调用实现时间循环 自关联实现滑动时间窗口 扩展基于自然周的的滚动时间窗口计算 总结 时间滑动计算 今天遇到一个需求 ...

  3. JAVA使用反射获取对象的所有属性名

    public static void main(String[] args) { Field[] fields=BaseSalary.class.getDeclaredFields(); for (i ...

  4. ubuntu web服务器配置

    1.安装Apachesudo apt-get install apache2 查看状态: service apache2 status/start/stop/restartWeb目录: /var/ww ...

  5. 【剑指Offer】翻转单词顺序列 解题报告(Python)

    [剑指Offer]翻转单词顺序列 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-interviews 题 ...

  6. idea使用教程-常用快捷键

    [1]创建内容:alt+insert [2]main方法:psvm [3]输出语句:sout [4]复制行:ctrl+d [5]删除行:ctrl+y [6]代码向上/下移动:Ctrl + Shift ...

  7. 【服务器】【环境搭建】WordPress建立数据库连接时出错---问题---解决

    这意味着您在wp-config.php文件中指定的用户名和密码信息不正确,或我们未能在localhost联系到数据库服务器.这可能意味着您主机的数据库服务器未在运行. 您确定用户名和密码正确吗? 您确 ...

  8. 基于Spring MVC + Spring + MyBatis的【图书信息管理系统(二)】

    资源下载:https://download.csdn.net/download/weixin_44893902/35123371 练习点设计:添加.删除.修改 一.语言和环境 实现语言:JAVA语言. ...

  9. Ubuntu18.04安装/卸载NVIDIA显卡驱动

    1 显卡驱动下载 官网:NVIDIA 搜索适合本机的驱动 获取最新版本驱动 立即下载 文件 以上,显卡驱动下载完成. 2 显卡驱动安装 2.1 添加可执行权限 进入驱动文件目录sudo chmod a ...

  10. xorm 条件查询时区的问题

    问题描述:如果在查询的时候,直接传时间格式作为条件,时间会被驱动程序转为UTC格式,因此会有8个小时的误差. 解决方案1: 将查询时间转为字符串 db.where("time > ?& ...