Apache Pulsar消息去重原理与源码分析

文章目录


背景

在消息队列系统中,生产者SDK在生产时通常存在两种类型的重试。

  • 1.生产请求超时,SDK自动重试,此时重试请求的内容不变。
  • 2.SDK生产请求向用户侧报错,用户可能尝试重新发送该消息内容。但对mq来说前后是不同的生产请求。

Pulsar中可以针对情况1进行消息去重,以避免SDK底层生产超时重试导致的生产重复。如果不开启消息去重则生产请求超时重试会导致消息重复存储,如下图:
在这里插入图片描述
如果开启消息去重则生产请求超时重试时只要有消息持久化成功后续的重试请求都不会导致消息持久化存储,如下图:
在这里插入图片描述


原理

Pulsar支持在Broker、Namespace、Topic级别开启消息去重功能。其中Broker级别开启开关为brokerDeduplicationEnabled默认为false。
Namespace级别开启可通过如下命令:

bin/pulsar-admin namespaces set-deduplication public/default --enable

Topic级别开启可通过如下命令:

bin/pulsar-admin namespaces set-deduplication public/default --disable

开启消息去重时,broker将每个producer最大的sequenceId存储在哈希表中。如果收到的生产请求中sequenceId小于该producer现有的sequenceId,则这条消息为重复的消息,不进行处理。Broker将每个topic的(producerName, sequenceId)定期snapshot在cursor中,当broker故障分区转移时,新broker将从snapshot重新恢复哈希表。但哈希表中producerName的最新sequenceId可能并不在snapshot中,因此broker还需要从topic ledger读取最新的N条Entry,并将entry中记录的(producerName, sequenceId)更新到哈希表中,以确保不会因为故障分区转移导致哈希表数据不完备。

  • producerName:可由用户在SDK侧创建topic producer时设置,若未设置则server端在handleProducer方法里生成唯一性Name并返回给客户端
  • sequenceId:Pulsar SDK为一次生产请求分配的唯一性Id

如源码所示,线程池周期性执行定时任务将该broker加载的topic的(producerName, sequenceId)进行snapshot,任务执行周期通过brokerDeduplicationSnapshotFrequencyInSeconds配置。

  • 14
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值