TDMQ Pulsar 3.0 引擎版本支持更大规模延迟消息,该功能针对海量延迟场景进行了深度优化,支持百万级别的延迟消息堆积处理,同时能够保证消费进度的准确性与稳定性,满足更多长链路业务(如远期订单关闭、长周期定时任务)的诉求。能有效解决电商、社交、金融等行业在定时任务调度、延迟通知等场景下的性能瓶颈问题。
大规模延迟消息策略
背景介绍
在分布式系统中,很多业务逻辑并不是“立刻执行”,而是“到了某个时间再执行”。消息队列的延迟消息能力,正是为这类场景而生。典型使用场景包括:订单超时未支付自动关单、营销活动定时触达、失败请求按退避策略重试等。这些场景的共同特点:消息的产生和消费之间存在一段可预期的时间差。延迟消息将这段“等待”交给消息队列管理,业务方只需在发送时指定到期时间,消费端在消息到期后自动收到投递,逻辑简洁、解耦彻底。但当延迟消息量级从万级攀升到百万级,Apache Pulsar 社区方案会引发:
消息空洞问题:当延迟消息较多且到期时间分布不均时,大量未到期消息会长时间占据消费位点,形成空洞并导致消费进度无法推进。一旦主题发生重载,内存中尚未持久化的这部分进度就会丢失,已投递的消息被重新拉起,进而引发大规模重复消费。
内存占用和索引重建耗时:Apache Pulsar 延迟消息索引默认全量加载到内存。消息规模一旦上来,内存占用和索引重建耗时都会成为不容忽视的瓶颈。社区高版本虽引入了 Bucket 化持久存储来缓解,但 Bucket 的管理、合并及元数据存储(依赖 ZooKeeper 的 Cursor Properties)本身又带来了新的复杂性。
功能架构
TDMQ Pulsar 大规模延迟消息方案:外部多级时间轮索引,不依赖内存构建延迟索引,主题中只记录最近到期的延迟消息,降低消费空洞规模,使得在百万级场景下内存占用与重复消费风险同时可控。

核心特性
把不同时间跨度的延迟索引拆分到不同维度的索引主题,系统只在临近投递时逐步加载更细粒度的索引,避免全量索引常驻内存。内存中始终只持有当前加载的索引数据,无论延迟消息总量是十万还是百万,内存占用都可控。索引主题的全部消息消费完成后自动删除,无需人工清理。
延迟消息到期后会从业务主题中读取原始消息并重新写入,消费端跳过尚未到期的消息、仅处理重新写入的到期消息,从而将消息空洞的范围从全量延迟消息收敛到临近投递的分钟级窗口内,避免了大规模空洞的产生。
TDMQ Pulsar 大规模延迟消息对客户端完全透明——延迟消息照常发送到业务主题,生产消费链路的处理逻辑与原来完全一致,客户端无需任何改造。服务端保证消息 ID 在生产、存储、消费全链路中保持一致,消息查询、消息轨迹等运维能力天然兼容,无需额外适配。
使用教程
使用建议:
若业务场景下消息空洞数量未超过1万,建议不启用大规模延迟消息功能。
启用大规模延迟消息需确保主题的消息保留时间超过最长延迟时间,否则可能导致未到期延迟消息丢失。
1 分钟内到期的延迟消息数量应控制在 100 万以内。若超过此数量,可能导致消息投递延迟、时间不准确等问题。
Exclusive/Failover 订阅模式本身不支持延迟消息功能,不建议在此类模式下使用大规模延迟消息策略,以免增加额外开销。
避免使用 TDMQ_DELAY_INDEX 作为命名空间,以免与大规模延迟消息的系统命名空间冲突,导致监控数据异常。
避免使用 TDMQ_Delay_Cursor 作为订阅名,否则可能与延迟消息的系统订阅名冲突,造成消息丢失或无法消费。
使用大规模延迟消息策略时,系统可能会在业务主题中创建以“tdmq-internal_”为前缀的生产者。
请勿强制删除已启用大规模延迟消息策略的主题。
建议将延迟消息与非延迟消息分别使用不同主题进行管理。即定时与延迟消息发送到一个固定的 Topic,普通消息发送到另一个 Topic 中,方便后续的管理与维护,增加稳定性。
使用定时和延时两种类型的消息时,请确保客户端的机器时钟和服务端的机器时钟(所有地域均为 UTC+8 北京时间)保持一致,否则会有时差。
定时和延时消息在精度上会有1秒左右的偏差。
定时和延时消息不支持 batch 模式(批量发送),batch 模式会引起消息堆积,保险起见,请在创建 producer 的时候把 enableBatch 参数设为 false。
定时和延时消息的时间范围最大均为10天。如果生产延迟消息超过 10 天,可能会导致客户端阻塞或反复重连。
定时和延时消息的消费模式仅支持使用 Shared 模式进行消费,Key_Shared 模式禁止使用。