延时任务队列-单机支持每秒10万延时消息高效触发(可部署多台提供更高并发)

本文探讨了多种延时队列实现方案,包括定时扫描表、Redis、Java DelayQueue、消息队列等,并分析了各自的优缺点。最终提出了自行实现轻量级延时队列的想法。

本文方案是看了58的一位架构师的分享,但并没有实现细节。本文是对方案的深入研究及代码实现


业务场景


1.下单之后如果三十分钟之内或12小时没有付款就自动取消订单


2.下单成功后60s之后给用户发送短信通知


3.用户希望通过手机远程遥控家里的智能设备在指定的时间进行工作。这时候就可以将用户指令发送到延时队列,当指令设定的时间到了再将指令推送到只能设备。


4. 七天自动收货


5.一定时间后自动评价


6.业务执行失败之后隔10分钟重试一次


…….



吐舌头本质都是过一段时间后才执行任务



下单成功后60s之后给用户发送短信通知为例。


方案一: 定时扫描表



实现:启动一个定时任务,每分钟查一次数据库表,把下单成功超过60秒并且没有发过短信通知的的取出来,然后去处理。


缺点:
1.如果数据量很大,查表轮询效率就低。
2.每分钟轮询一次增加了数据库压力。
3.如果是增大轮询时间间隔,那么时效性(准确性)又降低了



方案二: redis


实现:通过zset机构模拟,定时器去读zset数据去处理。


不足:

1.数据量大,一zset性能有问题。 当然可以多定义几个zset,再数据量大的时候分散到不同zset里面,但存和定时器去读的复杂性增加了。
2.消息处理失败是不能被恢复。也有考虑过将分为TODO和Doing两条队列。但是由于Redis的事务特性,并不能做到完全可靠;并且检查Doing超时的逻辑也略复杂
并不是成熟方案,需要自己去实现。


方案三: JAVA DelayQueue

实现:DelayQueue本身就是延迟队列


不足:

1.通过先将消息排序再定时触发的方式来实现延迟消息。所以大量消息时,性能不能保证
2.想提供一定可靠性(如数据持久性),扩展性不方便
3.分布式需要额外实现


方案四: MQ


实现:老版本的MQ大多没有延时队列的实现。
       不过现在新版本慢慢有了延时投递的功能。
如:ActiveMQ 可以延时投递,但有人测试在往队列中投递大量(10w+)定时消息之后,ActiveMQ的性能将会变得接近不可用,大量的消息挤压得不到投递,可多机。
      RocketMQ 支持定时消息,但是不支持任意时间精度,支持特定的level,例如定时5s,10s,1m等。
     RabbitMQ 通过他的一些特性也可以模拟出延迟队列的功能,或者有一些第三方插件
 
完善的MQ系统可实现一个高可靠的分布式延迟消息队列。仍在发展中,但还没有完全比较专用的延迟消息功能






方案五: 自己实现延时MQ
有能力可以做,mq实现起来还是耗费资源的




方案六: 自己实现延时队列


我们自己实现轻量级的延时队列。


初级版本目标:
       网络或down机允许消息丢失。即业务完整性不保证
       支持高并发
       不提供客户端

       只做一个内嵌的jar,不单独做一个成品应用服务

 

 

源码:https://gitee.com/itman666/wheel-timer-queue

详细介绍请看wiki: https://gitee.com/itman666/wheel-timer-queue/wikis/Home 

1.  前言 1.1.  项目简要说明 VMS Cloud Event模块是承载海量设备事件上报的核心组件,负责事件过滤、转发、存储等处理逻辑。当前依赖的公共组件EventCenter存在异常事件处理缺失(失败消息丢弃)、时效性不足(无延迟触发)、扩展性弱(无法适配复杂场景)等瓶颈。本项目目标是通过扩展死信队列(DLQ)与延迟队列功能,解决事件可靠性与时效性问题,为设备事件处理提供错误隔离、问题追踪、定时触发等能力,支撑VMS系统核心事件链路的稳定性。 1.2.  任务概述 本任务为VMS Cloud Event模块的公共组件开发,属于对现有EventCenter组件的低侵入式扩展,重点实现死信队列(错误消息隔离、重试、存储)与延迟队列(定时触发、灵活延迟)功能,同时提供配置管理、监控告警等配套能力,不修改EventCenter原生核心逻辑(如send()、registerBroadcast())。 1.3.  可用资源 EventCenter公共组件(现有基础)。 Kafka消息队列(用于主事件处理)。 Redis缓存集群(若采用延迟队列ZSet方案)。 1.4.  术语定义 死信队列(Dead Letter Queue, DLQ):存储无法正常消费的异常消息(如重试耗尽、消费失败),用于错误隔离与问题排查。 延迟队列(Delayed Queue):支持消息在指定延迟时间后被消费,用于异步定时任务(如定时删除事件)。 指数退避原则:初始等待时间基础上,可重试错误时等待时间以指数级增长(如1s→2s→4s)。 EventCenter:现有公共组件,提供事件发送、处理器注册等基础能力,支持Kafka、Local实现。 1.5.  参考资料 kafka官方文档(Apache Kafka Documentation):用于死信队列自定义拦截器实现参考。 EventCenter现有设计文档(Event Center 使用说明文档 - CRD_EP_Software_Service - Confluence)及EventCenter学习报告(EventCenter组件学习报告 - CRD_EP_Software_Service - Confluence):包含模块结构、核心接口及消息处理模式说明。 kafka消息范式调研报告(kafka消息范式扩展调研报告 - CRD_EP_Software_Service - Confluence):包含kafka消息范式扩展概述,死信队列延迟队列设计与实现。 2.  需求分析 需求分析文档链接:《Event死信队列延迟队列调研与应用》需求分析 - CRD_EP_Software_Service - Confluence 3.  原理概述 3.1.  EventCenter组件概述 EventCenter整体架构与核心设计 EventCenter是一款支持消息队列适配的事件处理组件,采用模块化分层架构,核心目标是屏蔽底层消息队列差异,提供统一的事件发布-订阅能力。其架构设计如下图所示 EventCenter的模块化设计实现了“逻辑解耦+灵活扩展” 如上图所示,核心模块包括: eventcenter-api:对外提供统一接口层(事件发送、处理器注册/解注册、资源销毁),定义事件基类(BaseEvent、EventV2、DomainEvent),屏蔽底层实现细节。 eventcenter-core:与消息队列无关的通用逻辑层,负责事件路由(广播/单播策略)、线程池管理(消费者线程隔离)、全局配置解析(CommonProperties)等。 eventcenter-port-系列:适配不同消息队列的实现层: eventcenter-port-kafka:基于Kafka的分布式事件实现,支持并发场景(分片、压缩),兼容广播/单播模式。 eventcenter-port-local:进程内事件总线,无广播/单播区分,依赖内存映射表实现线程间通信。 eventcenter-port-domain:基于DDD的领域事件总线,支持同步/异步订阅(通过ConcurrentHashMap管理订阅者集合)。 eventcenter-port-redis(已弃用):早期Redis实现,当前版本不再维护。 模块化设计的优势在于:通过替换Port层实现(如从Kafka切换到Local),业务逻辑无需修改,极大提升了组件的灵活性和适配性。 EventCenter的核心能力通过接口与关键类实现,以下为核心要素解析: 作为组件入口,EventCenter接口定义了事件处理全生命周期的核心方法: 事件发送:支持send(topic, event)(随机分区)、send(topic, key, event)(Key哈希分区)、send(topic, partition, event)(指定分区)等方式,支持回调(EventFuture)和序列化(JSON/Kryo)配置。 处理器注册:区分广播(registerBroadcast)与单播(registerUnicast)模式,支持自定义线程池(executorService)和分区分配策略(如COOPERATIVE_STICKY);提供registerWithoutThreadPool接口(业务自管理线程)。 资源管理:unregister解注册处理器,destroy销毁实例并释放资源(支持按需销毁线程池)。 事件基类(eventcenter-api): BaseEvent<T>:泛型基类,定义filterKey(过滤键)、timeStamp(时间戳)、message(消息体),为事件标准化提供基础。 EventV2<T>:支持Kryo序列化的泛型类,适用于复杂对象传递(如设备事件中的嵌套结构)。 DomainEvent:领域事件接口,定义id()(唯一标识)、occurredOn()(发生时间)、type()(事件类型),适配DDD设计。 处理任务类(eventcenter-core): DataProcessor/GenericDataProcessor封装事件处理逻辑(调用EventHandler.handleEvent),统一异常处理,确保消费失败时可捕获并记录。 Kafka实现类(KafkaEventCenter): KafkaEventCenter实现EventCenter接口,处理消息发送(分片、压缩)、订阅者注册(广播/单播)及资源释放;KafkaConsumerConfig/KafkaProducerConfig支持分区分配策略(如COOPERATIVE_STICKY)和自定义分发器。 Local实现类(LocalEventCenter) VMS Cloud Event模块通过EventCenter实现事件的发布与消费,核心流程如下: 初始化注册:服务启动时,通过registerBroadcast或registerUnicast注册事件处理器(继承EventBusSubscriber,实现handleEvent方法),指定消费模式、线程池及分区策略。 事件发送:生产者调用send系列方法发送事件(支持随机/Key哈希/指定分区),附加回调处理发送结果。 事件消费:消费者线程池异步执行EventHandler.handle方法处理事件(广播模式下所有实例接收,单播模式下仅一个实例处理)。 资源释放:通过unregister或destroy释放资源(支持按需销毁线程池)。 3.2.  死信队列延迟队列原理概述 3.2.1死信队列 定义:死信队列(Dead Letter Queue, DLQ)是用于存储无法被正常消费的异常消息的特殊队列,核心价值在于错误隔离、问题追溯与数据补偿。 方案选择:基于Kafka消费者拦截器(Consumer Interceptor)实现,通过非侵入式扩展EventCenter消费流程,精准捕获消费阶段的失败消息。 实现原理: 在Kafka消费者端实现ConsumerInterceptor接口,拦截poll()返回的消息并注入以下处理逻辑: 异常捕获:监听业务消费逻辑(如EventHandler.handle())抛出的异常(包括业务逻辑错误、反序列化失败、消费者临时宕机等); 消息隔离:通过独立Kafka生产者将失败消息(含原始内容、异常堆栈、重试次数等上下文)发送至专用死信Topic(如vms_event_dlq); 偏移量提交:仅在死信消息发送成功后,通过KafkaConsumer.commitSync()提交原消息的偏移量,避免因死信发送失败导致消息重复消费; 重试集成:若未达到最大重试次数(默认3次),将消息路由至延迟队列(通过预设延迟等级实现重试间隔),到期后重新消费。 VMS业务场景适配: 针对现有EventCenter异常事件处理的痛点(消息堆积阻塞主队列、上下文分散难追溯),死信队列通过“拦截-隔离-告警”流程优化: 拦截:实时捕获消费失败消息,避免主队列被异常消息阻塞; 隔离:将失败消息集中存储至死信Topic,保障主队列吞吐量; 告警:监控死信Topic堆积量(阈值可配置,如100条),触发告警后通过人工/自动补偿流程(如修复后重新投递)减少数据丢失风险。 3.2.2延迟队列 延迟队列支持消息在指定延迟时间后被消费,典型场景包括: 定时任务触发(如任务30分钟后删除)。 失败重试(如消费失败后5分钟重试)。 订单超时取消(如未支付订单30分钟后自动关闭)。 延迟队列方案:Kafka分区延迟方案 实现原理:仿照RocketMQ的18级固定延时等级设计(如1s、5s、10s、30s、1min、5min…2h等),在Kafka中为每个延时等级预设独立队列(可通过分区或独立Topic实现)。由多个专用转发任务分别订阅所有18个延时等级队列,通过pause()暂停未到期队列的消费,并动态根据各队列中最早到期消息的时间戳,定时调用resume()恢复到期队列的消费,将消息转发至目标业务Topic。固定延迟等级可满足大部分需求:参考RocketMQ等成熟中间件的设计经验,实际业务中延迟需求多集中于短时间内的固定等级,预设18级左右的延迟等级已能覆盖90%以上的业务场景,无需完全自定义延迟时间。 典型VMS业务场景: 1.在VMS Event模块中,设备管理场景,设备删除操作需确保“先删除事件上报,再删除设备”的时序性。若直接删除设备后仍有事件上报,会导致“已删除设备存在事件上报”的数据不一致问题;通过延迟队列可实现:删除设备时先发送“删除事件上报”消息,延迟一定时间后再执行设备删除操作,确保事件上报完全处理后再删除设备,避免数据残留 2.在VMS AI模块中也有类似场景,设备上报的抓图在设备删除时也需要先删除抓图上报,再删除设备;删除设备时先发送“删除抓图上报”消息,延迟一定时间后再执行设备删除操作,确保事件上报完全处理后再删除设备,避免数据残留。 3.设备升级任务容错:设备升级流程涉及多个微服务协同获取设备信息并执行升级。若服务A获取设备信息后宕机,任务因无其他服务接管而阻塞。通过延迟队列优化后,流程变为触发设备升级时,向普通队列发送“设备升级通知”消息,所有订阅该Topic的微服务均可消费;同时系统向延迟队列发送一条“延迟重试升级”消息延迟队列在5分钟后触发消息的消费逻辑,其他存活服务重新获取设备信息并完成升级,确保任务最终执行,避免阻塞。 根据现有场景进行分析:大多数为非精准匹配场景,即不追求绝对的延迟误差,所提供延迟队列需要支持按就近匹配策略将延迟消息发送至按策略匹配与需求延时时间最接近的延时分区。 针对Topic和分区进行考虑: 每个延时等级对应1个Topic 优点:高隔离性:不同延时等级的消息完全隔离在独立Topic中,某等级的消息堆积、故障不会影响其他等级(如1s延时的高并发消息不会占用2h延时的资源)。配置灵活性:每个Topic可独立设置参数。消费逻辑简单:转发任务可直接订阅对应Topic,无需额外过滤或映射。扩展性强:新增延时等级时只需创建新Topic,不影响现有系统。 缺点:资源消耗大:每个Topic需占用Broker的元数据存储、文件句柄、网络连接等资源,18个Topic的资源开销远高于1个Topic(尤其是每个Topic配置多分区时)。管理复杂度高:需单独监控、运维18个Topic,增加管理负担。 每个延时任务对应一个分区:为了避免轮询定时任务的出现,依旧需要对应分区数的消费者分别订阅每一个分区 优点:资源利用率高:所有延时等级的消息共享1个Topic的资源,大幅降低资源消耗。管理简单:仅需维护1个Topic,监控、配置、故障排查更高效。 缺点:隔离性弱:所有延时等级共享Topic的配置;配置灵活性低:无法针对单个延时等级调整参数;扩展性受限:新增延时等级需扩容Topic的分区数,虽Kafka支持动态扩容,但会影响现有消费者的分区分配,且需维护“分区→延时等级”的映射表。 结合Topic申请方式以及对隔离性的核心需求,延迟队列采用多独立Topic方案,为每个固定延迟等级(如1s、5s、30s等)分配独立Kafka Topic(如vms_delay_1s、vms_delay_5s、vms_delay_30s),通过专用转发任务实现消息的定时触发。 高隔离性:不同延迟等级的消息独立存储,避免某等级消息堆积或故障影响其他等级; 灵活配置:支持为高流量延迟等级和低流量延迟等级采用不同配置; 易扩展性:新增延迟等级时仅需创建新Topic,无需修改现有消费逻辑; 运维友好:通过统一的Topic命名规范和监控指标,降低管理复杂度。请根据以上修改的概要设计将后续内容进行修改:4.  系统架构描述 4.1.  概述 模块遵循“低侵入、高内聚”原则,基于EventCenter扩展,划分为4大模块:配置管理、死信处理、延迟消息管理、监控与告警。与EventCenter原生模块(消息生产者、消费者)解耦,通过接口扩展实现功能。 4.2.  模块结构 配置管理模块:提供策略配置入口,提供方法设定配置参数,以及获取当前配置。 死信处理模块:依赖配置管理模块配置的各参数(如重试策略,重试次数等),调用延迟消息管理模块提供的方法进行重试,向监控模块提供死信数据。 延迟消息管理模块:向监控模块上报触发状态。 监控与告警模块:接收死信处理模块和延迟消息管理模块的数据。 4.3.  模块描述和建模 配置管理模块 功能:管理死信队列(开关、重试次数/策略)的配置,支持开发人员动态设置。 对外提供功能:enableDeadLetter()、setRetryCount()、setDelayPolicy()等接口。 流程:开发人员通过接口设置参数→配置存储至DeadLetterConfig→其他模块通过DeadLetterConfig获取配置。 死信处理模块 功能:捕获消费失败消息,执行重试逻辑(重试时间通过延迟队列实现),重试耗尽后发送至DLQ,提交偏移量并记录日志。 核心对象:DeadLetterInterceptor(Kafka拦截器)、RetryPolicy(重试策略枚举)。 流程:消费失败→拦截器捕获异常→检查重试次数→未耗尽则通过延迟队列重试→耗尽则发送至DLQ→提交偏移量→记录日志。 延迟消息管理模块 功能:实现延迟消息发送、到期触发、失败重试。 核心对象:RedisDelayedMessageManager(ZSet方案)、KafkaPartitionDelayedMessageManager(分区方案)。 流程(kafka分区延迟):由对应专用转发任务分别订阅所有18个延时等级topic/分区,通过pause()暂停未到期队列的消费,并动态根据各队列中最早到期消息的时间戳,定时调用resume()恢复到期转发任务的消费,将消息转发至目标业务Topic。 监控与告警模块 功能:监控死信堆积量、延迟消息触发成功率,支持日志导出与状态查询。 对外提供功能:getDlqBacklog()、getDelayedSuccessRate()。 流程:订阅DLQ Topic统计堆积量→统计延迟消息触发数据→提供接口查询。 4.4.  流程设计 4.4.1. 死信处理流程: 实现原理: 在Kafka消费者端实现ConsumerInterceptor接口,拦截poll()返回的消息。当消费逻辑(如EventHandler.handle())抛出异常时,拦截器捕获失败消息,通过独立生产者将其发送至死信Topic(如vms_dlq_topic),并提交原消息的偏移量(避免重复消费)。 关键流程: 消费者从Kafka拉取消息(poll())。 拦截器预处理消息(如记录元数据)。 业务逻辑消费消息(调用handleEvent())。 若消费成功,正常提交偏移量;若失败,拦截器: 记录失败原因(异常堆栈、重试次数)。 通过独立生产者将消息发送至死信Topic。 提交原消息偏移量(避免重复消费)。 4.4.2. 延迟处理流程 Kafka分区分桶方案:仿照RocketMQ的18级固定延时等级设计(如1s、5s、10s、30s、1min、5min…2h等),在Kafka中为每个延时等级预设独立队列。由对应专用转发任务分别订阅所有18个延时等级队列,通过pause()暂停未到期队列的消费,并动态根据各队列中最早到期消息的时间戳,定时调用resume()恢复到期转发任务的消费,将消息转发至目标业务Topic。 关键流程: 消息生产:根据延迟时间将消息发送至对应分区(如topic-delay-5s、topic-delay-30s)。 转发任务:针对对应分区的消费者(转发任务),调用pause()暂停消费,暂停时间为该分区最早未消费消息的剩余暂停时间。 定时恢复:针对对应分区的消费者(转发任务),对到期的分区调用resume()触发转发任务,转发至相应目标topic。 5.  任务(或进程/线程)设计 5.1.  原因 需独立线程处理死信发送、延迟消息扫描等任务,避免阻塞主消费/生产流程。 5.2.  任务(或进程/线程)内部流程 死信发送线程: 职责:接收拦截器传递的失败消息,通过独立Kafka生产者异步发送至DLQ Topic。 流程:拦截器传递失败消息→线程池异步处理→发送至DLQ→记录日志。 延迟扫描线程(Redis ZSet方案): 职责:按配置间隔(默认1秒)扫描Redis ZSet,提取到期消息触发发送。 流程:定时触发扫描→获取到期消息→发送至目标Topic→失败则重新插入ZSet。 分区恢复线程(Kafka分桶方案): 职责:根据到期时间恢复到期分区(转发任务)的消费。 流程:根据当前时间与分区到期时间,到期则调用resume()恢复消费。 5.3.  任务(或进程/线程)间通信 死信处理模块向监控模块发送死信日志(含消息ID、失败时间)。 延迟消息管理模块通过独立线程进行延迟扫描/分区恢复。 6.  数据库及中间件设计 6.1.  选型 Kafka:用于主消息队列、DLQ Topic及Kafka分桶方案的延迟分区。EventCenter原生使用。 Redis(仅Redis ZSet方案):用于暂存延迟消息。选择原因:有序集合(ZSet)支持按时间戳高效扫描。 6.2.  数据库表结构设计 Redis配置(ZSet方案): Key格式:vms_delay_<topic>(如vms_delay_device_event),score为到期时间戳; 持久化:启用AOF持久化(appendonly yes),确保延迟消息不丢失; 过期时间:无(延迟消息通过扫描触发后自动删除)。 6.3.  历史数据归档设计 按业务需求定义死信日志保留时间,转存或导出。 7.  跨区同步设计 7.1.  数据库同步设计 不涉及 7.2.  业务同步设计 不涉及 8.  可靠性设计 8.1 SLO设计 SLI SLO目标 DLQ处理延迟 ≤200ms 死信堆积告警 阈值 > 1000条/小时 8.2 调用链可靠性设计 复用EventCenter调用链可靠性设计 8.3 中间件可靠性设计 复用EventCenter相关设计 8.3.1 数据库可靠性设计 不涉及 8.3.2 消息队列可靠性设计 复用EventCenter相关设计 8.3.3 缓存可靠性设计 复用项目相关设计 8.4 容量设计 8.4.1 容量规划 不涉及 8.4.2 容量超限设计 不涉及 9.  数据合规设计 不涉及 9.1.  分区隔离 不涉及 9.2.  访问控制 不涉及 9.3.  加密存储 不涉及 9.4.  加密传输 不涉及 10.  接口概要设计 10.1.  概述 本模块为EventCenter公共组件的扩展部分,通过低侵入式接口提供功能,供开发人员调用。 10.2.  接口分类与功能 接口名称 交互模块 接口描述 enableDeadLetter(topic, enable) EventCenter 开发人员调用,启用/禁用指定Topic的死信队列(低侵入,不修改原生send()逻辑)。 setRetryCount(topic, count) EventCenter 开发人员调用,重试次数设置(默认为3次) setRetryPolicy(topic, policy) EventCenter 开发人员调用,重试策略设置(默认为指数退避) sendDelayedEvent(topic, event, delayS) EventCenter 开发人员调用,发送Redis ZSet方案的延迟消息(兼容原生send()的序列化配置)。 sendDelayedEvent(topic, event, delayLevel) EventCenter 开发人员调用,发送kafka分区方案的延迟消息(自动路由至对应分区)。 补充,针对死信配置,可以不调用死信接口,可以通过重载send方法(例如,补充参数死信开关,死信配置等)或者通过配置文件(在死信配置类上添加@ConfigurationProperties(prefix = "eventcenter.deadletter")注解)。(同理可以包装handler,重载register方法)以方便开发人员调用为原则。 10.3. 兼容性说明 新增接口不影响EventCenter原生方法 11. 用户支持设计 支持运维人员查询死信消息,导出告警日志 12.  用户界面概要设计 不涉及 12.1.  界面组织 不涉及 12.2.  界面设计 不涉及 13.  开发环境、测试环境及部署环境 13.1.   测试环境 组件开发完成后,编写demo调用组件进行测试,测试中模拟1000条/秒消息压力,验证死信处理并发能力、延迟消息扫描误差。 13.2.  部署环境 复用EvenCenter相关部署 13.3.  成本预算 不涉及;并且需要根据以下评审意见补充:1.整理需要提供哪些新的接口,哪些方法重载了,需要写完善;2.概要设计中压力测试部分,消息压力量设计偏小,进行修改;3.尽量接入VMS Event模块,测试中设计死信注入故障(例如:模拟消费者崩掉的场景);4.补充压力测试模块数据和环境;5.分离强制延迟时间性能指标和非强制延迟时间性能指标,分别计算;5.结合实际业务申请topic方式,死信topic应修改为不支持开发人员配置;6.补充内容:未发现对应死信topic创建应该告警
最新发布
09-27
1.    前言 1.1.  背景和目标 VMS Cloud Event模块作为承载海量设备事件上报的核心组件,负责事件过滤、转发、存储等复杂处理逻辑。当前依赖的公共组件EventCenter仅支持基础订阅消费能力,存在以下瓶颈: 异常事件处理缺失:失败事件直接丢弃,无重试/隔离机制; 时效性不足:缺乏延迟触发能力(如定时删除事件); 扩展性弱:无法适配新增的复杂业务场景(如设备批量操作或批处理)。 本模块在项目中处于事件处理链路的核心地位,直接影响设备事件的可靠性与时效性。本需求分析文档的撰写目标是明确死信队列延迟队列的功能需求、非功能性需求及实现方案,为后续开发提供指导。 /**补充:vms业务汇总*/ 1.2.  定义 死信队列(Dead Letter Queue, DLQ):存储无法被正常消费的异常消息(如重试耗尽、消费失败),用于错误隔离与问题排查。 延迟队列(Delayed Queue):支持消息在指定延迟时间后被消费,用于异步定时任务(如定时删除事件)。 EventCenter:现有公共组件,提供事件发送、处理器注册等基础能力,支持Kafka、Local实现。 指数退避原则:设置初始等待时间,发生可重试错误时重试,再次发生错误时等待时间会以指数级别增长。 1.3.  参考资料 kafka官方文档(Apache Kafka Documentation):用于死信队列自定义拦截器实现参考。 EventCenter现有设计文档(Event Center 使用说明文档 - CRD_EP_Software_Service - Confluence)及EventCenter学习报告(EventCenter组件学习报告 - CRD_EP_Software_Service - Confluence):包含模块结构、核心接口及消息处理模式说明。 kafka消息范式调研报告(kafka消息范式扩展调研报告 - CRD_EP_Software_Service - Confluence):包含kafka消息范式扩展概述,死信队列延迟队列设计与实现。 VMS Kafka Topic信息汇总表(VMS Kafka Topic信息记录 - CRD_EP_Software_Service - Confluence):包含现有的Kafka Topic信息记录。 2.    调研结果 2.1 死信队列(Dead Letter Queue, DLQ)设计与实现 2.1.1 死信队列核心价值 死信队列是存储“无法被正常消费的消息”的特殊队列,核心作用: 错误隔离:避免异常消息阻塞主消费流程,保障主队列吞吐量。 问题追踪:集中存储失败消息(含上下文、错误日志),便于定位根因。 数据补偿:支持人工/自动修复后重新投递,减少数据丢失风险。 2.1.2死信队列常见设计方案 方案1:基于Kafka消费者拦截器(Consumer Interceptor) 实现原理: 在Kafka消费者端实现ConsumerInterceptor接口,拦截poll()返回的消息。当消费逻辑(如EventHandler.handle())抛出异常时,拦截器捕获失败消息,重试逻辑运行完成后,通过独立生产者将其发送至死信Topic(如vms_dlq_topic),并提交原消息的偏移量(避免重复消费)。 关键流程: 消费者从Kafka拉取消息(poll())。 拦截器预处理消息(如记录元数据)。 业务逻辑消费消息(调用handleEvent())。 若消费成功,正常提交偏移量;若失败,拦截器: 记录失败原因(异常堆栈、重试次数)。 通过独立生产者将消息发送至死信Topic。 提交原消息偏移量(避免重复消费)。 优点: 完全基于Kafka原生API,无需引入外部中间件。 灵活控制重试策略(如最大重试次数、间隔)。 与业务代码解耦(拦截器逻辑独立)。 缺点: 需开发拦截器逻辑,增加代码复杂度。 独立生产者需处理线程隔离(避免阻塞主消费线程)。 依赖消费者端配置(需为每个消费者组启用拦截器)。 方案2:基于Kafka生产者回调(Producer Callback) 实现原理: 在消息发送阶段,通过生产者的Callback接口捕获发送失败的消息(如网络异常、Broker不可用),将其直接发送至死信Topic。此方案主要处理“发送失败”的消息,而非“消费失败”的消息。 关键流程: 生产者调用send()发送消息,附加Callback。 若消息成功写入Kafka(RecordMetadata返回),流程结束。 若发送失败(Exception抛出),Callback捕获异常,将原消息+异常信息封装后发送至死信Topic。 优点: 直接捕获发送阶段的失败消息,避免未达Broker的消息丢失。 实现简单(仅需在生产者端添加回调逻辑)。 缺点: 仅覆盖“发送失败”场景,无法处理“消费失败”的消息。 死信Topic需与主Topic同步扩容,增加运维成本。 方案3:Confluent平台DLQ支持(Kafka生态扩展) 实现原理: Confluent平台(Kafka商业发行版)提供内置DLQ功能,通过在消费者配置中指定dead.letter.topic.name,当消息消费失败(如反序列化异常、处理超时)时,Confluent客户端自动将消息转发至死信Topic。 优点: 零代码开发(仅需配置),集成成本低。 自动处理反序列化失败、消费超时等异常场景。 缺点: 依赖Confluent商业组件(需评估License成本)。 仅支持Confluent客户端(与原生Kafka客户端不兼容)。 无法自定义重试策略(依赖默认逻辑)。 其他中间件对比 RabbitMQ DLX:通过绑定“死信交换器”实现,支持消息拒绝、超时、队列满等场景自动路由。优点是原生支持,缺点是与Kafka技术栈不兼容。 RocketMQ DLQ:为每个消费者组自动创建死信队列(%DLQ%+组名),重试耗尽后自动存储。优点是无需开发,缺点是死信无法自动消费(需人工干预)。 方案4:补充(Spring kafka的死信队列支持) 现有EventCenter引入的SpringKafka版本:2.5.2 RELEASE(VMS v2.1.0_dev引入的springkafka版本是2.8.0) SpringKafka2.2 版本开始,提供 DeadLetterPublishingRecoverer和SeekToCurrentErrorHandler 工具类,用于捕获异常,但是该版本提供的重试策略是阻塞实现,通过Thread.sleep()实现。 SpringKafka2.8 版本:推出 DefaultErrorHandler,支持重试策略和 DLQ 配置,SpringKafka2.8版本以后支持的重试策略是非阻塞实现,通过消息头携带kafka_retryTimestamp实现时间戳调度的。 特性 Spring Kafka 2.5.2 Spring Kafka 2.8 重试机制 仅支持阻塞式RetryTemplate 新增非阻塞式RetryTopic 事务管理 基础事务支持 增强事务隔离级别,支持Exactly-Once语义 错误处理 需手动配置SeekToCurrentErrorHandler 内置CommonErrorHandler,简化错误处理逻辑 线程模型 基于ConcurrentKafkaListenerContainer 优化线程池调度,减少资源争用 Spring Boot兼容性 需Spring Boot 2.3.x/2.4.x 需Spring Boot 2.6.x+ 2.1.3 死信队列方案对比总结 消费者拦截器 消费失败消息隔离 自主可控、兼容原生Kafka 需开发拦截器,线程隔离复杂 生产者回调 发送失败消息隔离 实现简单、覆盖发送阶段 不处理消费失败场景 Confluent DLQ 快速集成、低代码场景 零开发、自动转发 依赖商业组件,License成本高 2.2 延迟队列(Delayed Queue)设计与实现 2.2.1 延迟队列核心价值 延迟队列支持消息在指定延迟时间后被消费,典型场景包括: 定时任务触发(如设备事件30分钟后删除)。 失败重试(如消费失败后5分钟重试)。 订单超时取消(如未支付订单30分钟后自动关闭)。 2.2.2 延迟队列常见设计方案 方案1:基于Redis有序集合(ZSet)的Kafka扩展 补充:EventCenter支持Kafka消息队列实现和Local版本实现,早期曾评估Redis(采用List)作为消息队列方案(eventcenter-port-redis),在EventCenter文档中描述了弃用,并没有描述弃用原因。 根据现有redis实现代码分析的弃用原因: 单线程消费模型:每个Topic的消费者任务(RedisUnicastConsumerTask/RedisBroadcastConsumerTask)由独立线程池(ThreadPoolExecutor(1,1,...))驱动; 资源消耗高:每个Topic需独立维护线程池(topicExecutorServiceMap)和消费者任务(topicTaskMap),随着Topic数量增长(如百个业务Topic),线程资源和内存占用将显著增加。 监控与运维工具缺失:Kafka有成熟的监控工具,而Redis Stream的消息堆积、消费延迟等指标需自定义采集。 而本方案使用Redis将延迟消息存入Redis Zset,一个定时任务线程对集合进行扫描,会避免起过多线程的问题; 实现原理: 结合Kafka与Redis,将延迟消息暂存于Redis ZSet(以到期时间戳为score),通过定时任务扫描ZSet,将到期消息发送至Kafka目标Topic。 关键流程: 消息生产:生产者将延迟消息(含事件内容、延迟时间)存入Redis ZSet(Key:vms_delay_queue,score=当前时间+延迟时间)。 扫描触发:定时任务(如每1秒)执行ZRANGEBYSCORE vms_delay_queue 0 <当前时间戳>,获取到期消息消息投递:将到期消息通过Kafka生产者发送至目标Topic(如vms_delete_event_topic)。 异常处理:Redis拉取操作本身可靠(依赖AOF持久化),但发送至Kafka可能失败,原因包括Kafka Broker不可用、网络故障或序列化错误。独立的该方案失败重试逻辑是发送失败时重新插入Redis Zset,实际中由于死信队列的扩展有重试机制,失败重试逻辑直接交由死信队列处理。并不做拉取成功或失败的判断,消息从Redis拉取同时直接删除redis中的消息,调用send()及相关方法发送至目标topic; 优点: 支持任意延迟时间。 可能可以复用现有Redis资源。 分布式友好(通过Redis主从复制保障高可用)。 缺点: 需开发定时扫描逻辑(需处理并发扫描、消息去重)。 依赖Redis持久化(如AOF)保障消息不丢失。 扫描间隔与精度权衡(间隔过小增加Redis压力,过大导致延迟误差)。 方案2:基于时间轮算法的Kafka内部扩展 实现原理: 时间轮(Time Wheel)是一种高效的延迟任务调度算法,通过“轮盘槽位”管理延迟任务。Kafka的KafkaDelayedMessage和Netty的HashedWheelTimer均基于此原理。在Kafka中,可扩展消费者端实现时间轮,将延迟消息按到期时间分配至不同槽位,轮盘转动时触发消息投递。 关键设计: 时间轮结构:轮盘分为多个槽位(如100个),每个槽位代表1秒。 消息入轮:计算消息到期时间与当前时间的差值,分配至对应槽位(如延迟5秒的消息放入槽位5)。 轮盘转动:每秒移动一个槽位,触发当前槽位的消息投递。 优点: 时间复杂度O(1),高吞吐量下延迟低(百消息/秒)。 无需外部存储(依赖内存),响应速度快。 缺点: 需深度修改Kafka客户端源码(开发难度大)。 内存限制(槽位数量与消息容量需平衡,大延迟消息可能跨多轮)。 消息持久化困难(内存数据易丢失,需结合日志备份)。 方案3:基于Kafka分区与消费者暂停的分桶策略 实现原理: 仿照RocketMQ的18级固定延时等级设计(如1s、5s、10s、30s、1min、5min…2h等),在Kafka中为每个延时等级预设独立队列(可通过分区或独立Topic实现,如topic-delay-level-01对应1s延时,topic-delay-level-18对应2h延时)。由多个专用转发任务分别订阅所有18个延时等级队列,通过pause()暂停未到期队列的消费,并动态根据各队列中最早到期消息的时间戳,定时调用resume()恢复到期队列的消费,将消息转发至目标业务Topic。 关键流程: 消息生产:根据延迟时间将消息发送至对应分区(如topic-delay-5s、topic-delay-30s)。 转发任务:针对对应分区的消费者(转发任务),调用pause()暂停消费,暂停时间为该分区最早未消费消息的剩余暂停时间。 定时恢复:针对对应分区的消费者(转发任务),对到期的分区调用resume()触发转发任务,转发至相应目标topic。 优点: 完全基于Kafka原生功能,无需外部组件。 分区隔离保障不同延迟消息的独立性。 缺点: 仅支持预设延迟等级(如5s、30s),无法动态调整。 分区数量随延迟等级增加而膨胀(如支持10种延迟需10个分区)。 需要维护多个分区,多个对应的转发任务。  其他中间件对比 RabbitMQ延迟交换器:通过x-delayed-message交换器实现,消息设置x-delay字段。优点是毫秒级精度,缺点是依赖插件且与Kafka不兼容。 RocketMQ延迟消息支持18级预设延迟(1s~2h),Broker暂存后转发。优点是原生支持,缺点是延迟等级固定。 2.2.3 延迟队列方案对比总结 Redis ZSet 自定义延迟 灵活 需开发扫描逻辑,依赖Redis 时间轮算法 高吞吐量、低延迟场景 高效、低延迟 开发难度大,内存依赖 Kafka分区分桶 预设延迟、原生依赖场景 无需外部组件 延迟等级固定,分区膨胀 补充:kafka分区方案和Redis Zset方案的多维度比较 从调研中一些典型的测试结果中得到的两方案在资源和性能方面的比较如下表: 方案 吞吐量 延时误差 资源消耗 适用场景 Redis ZSet 受限于Redis扫描效率与定时任务频率(如1秒扫描一次),单次扫描需处理大量到期消息时可能出现瓶颈(如百消息/秒需高频扫描); 和定时任务间隔时间有关,如1s间隔误差小于1s 存储:Redis内存占用高 计算:承担ZSet排序、扫描(ZRANGEBYSCORE)等操作; 有自定义延时的需求,短时延迟较多,数据量不是特别高的场景。 Kafka分区分桶 依赖Kafka分区并行能力(多分区可并行消费),每个分区独立resume后可并行转发,理论吞吐量更高(与Kafka集群规模正相关); 队首消息时间戳精度决定,延迟误差小; 存储:消息直接存在Kafka 计算:计算资源集中在Kafka消费者(转发任务) 数据量比较大,仅有特定等级的延时需求。 在整体数据量规模小的时候,Redis Zset方案有更好的性能,但随着数据量扩展,kafka分区方案性能更好。为了满足后续有可能的大量延迟队列使用,拟选用Kafka分区延迟的延迟队列方案。 3.    功能需求 3.1.  总体描述 本模块为VMS系统事件相关组件EventCenter的扩展模块,聚焦死信队列(DLQ)与延迟队列的功能实现,解决现有EventCenter的异常事件处理不完善、时效性不足问题。模块通过低侵入式扩展(最小化修改EventCenter原生代码)提供配置化管理、灵活的重试策略及定时触发机制,支持开发人员通过EventCenter原生接口调用扩展功能(如发送延迟消息、启用死信队列),运维人员通过配置平台管理策略(如重试次数、延迟等级)。 扩展模块架构如下图所示: 3.1.1. 需求主体 需求主体 主体介绍 开发人员 VMS业务系统开发者,调用EventCenter的接口开发消息队列相关功能(如设备事件上报),需通过扩展接口启用死信队列、发送延迟消息以及配置相关策略。 运维人员 VMS系统运维人员,负责监控死信堆积量。 3.1.2. 功能模块划分 功能模块 模块编号 模块描述 配置管理模块 01 管理死信队列(开关、重试策略)的全局配置,支持开发人员通过EventCenter接口传递配置。 死信处理模块 02 基于EventCenter消费者拦截器扩展,捕获消费失败消息,执行重试逻辑,发送至DLQ并记录日志,与EventCenter原生消费流程解耦。 延迟消息管理模块 03 两种延迟方案:Redis ZSet/Kafka分区分桶(目前选用Kafka分区方案,可调整); 支持发送延迟消息,用延迟队列时通过调用相关方法选择延迟时间 监控与告警模块 04 监控死信堆积量、延迟消息触发成功率。 3.1.3. 用例图 3.2.  功能模块1:配置管理模块(模块编号01) 需求编号 需求说明 需求限制/背景 关联主体 优先级 MQE-01-0001 支持死信队列开关配置(默认关闭) 开发人员通过EventCenter的相关接口启用,避免非必要资源消耗。 开发人员 高 MQE-01-0002 支持自定义重试次数(默认3次) 开发人员通过接口设置,某些业务需修改重试次数。 开发人员 高 MQE-01-0003 支持重试间隔策略配置(默认指数退避,可选固定间隔、自定义) 开发人员通过setRetryPolicy(topic, policy)接口设置,默认指数退避(如1s→2s→4s)。【该需求是建立在可自定义时间的基础上,如果依照Kafka分区方案,只能选预设的相应等级】 开发人员 高 MQE-01-0004 支持死信名称配置(默认业务名_dlq_topic), 开发人员开启死信队列时需要设置对应业务的死信名称,未自定义业务使用默认。 开发人员 中 配置管理流程图如下图所示: 3.3.  功能模块2:死信处理模块(模块编号02) 典型场景:事件消费时,因业务逻辑异常导致消费失败,重试3次(默认值)后仍失败,消息需进入死信队列,避免阻塞主流程。 需求编号 需求说明 需求限制/背景 关联主体 优先级 MQE-02-0001 基于EventCenter消费者拦截器扩展,无侵入式集成 拦截器实现ConsummerInceptor接口,不修改原生消费逻辑。 开发人员 高 MQE-02-0002 捕获消费失败消息 拦截器监听EventHandler.handleEvent()的异常抛出。 系统 高 MQE-02-0003 执行重试逻辑(基于配置的重试次数和间隔),重试时间通过延迟队列实现 重试期间记录重试次数,避免无限重试。 系统 高 MQE-02-0004 重试耗尽后,将消息发送至DLQ(含原消息体、异常堆栈、重试次数) 死信消息通过独立Kafka生产者发送,不阻塞主消费线程。 系统 高 MQE-02-0005 提交原消息偏移量(仅在死信发送成功后) 避免重复消费(通过KafkaConsumer.commitSync(offset)实现)。 系统 高 MQE-02-0006 记录死信日志(含消息ID、Topic、业务标识、失败时间、错误原因) 运维人员订阅死信topic,通过其中日志追溯上下文 运维人员 中 补充:如果死信消息发送至死信队列失败,应该设置重试机制(默认次数和策略),重试后仍然失败应该记录日志,并且检测对应死信队列的健康状态。 3.4.  功能模块3:延迟消息管理模块(模块编号03) 典型场景:VMS设备删除时,需先删除事件上报,然后延迟一定时间后删除设备,避免设备删除后仍有事件上报导致数据不一致。将写出两个方案的需求,kafka方案作为目前选择,redis zset方案作为备选。 3.4.1 Redis ZSet方案需求(备选) 需求编号 需求说明 需求限制/背景 关联主体 优先级 MQE-03-0001 支持开发人员通过sendDelayedEvent(topic, event, delayS)方法发送自定义延迟消息 延迟时间单位为秒(如30分钟=1800s),兼容任意延迟需求。(如需要扩展,添加时间转换或设置不同时间单位的参数) 开发人员 高 MQE-03-0002 消息存储至Redis ZSet(Key格式:vms_delay_<topic>) 按Topic隔离数据,避免不同业务消息混淆(如设备事件与订单事件)。 系统 高 MQE-03-0003 定时扫描ZSet(间隔可配置,默认1秒)获取到期消息 扫描线程独立于EventCenter主线程,避免资源竞争。 系统 高 MQE-03-0004 到期消息通过EventCenter的send()接口发送至目标Topic(默认原Topic) 开发人员可通过参数指定目标Topic(如sendDelayedEvent(topic, event, delayS, targetTopic))。 开发人员 高 3.4.2 Kafka分区延迟方案需求 需求编号 需求说明 需求限制/背景 关联主体 优先级 MQE-03-0011 支持开发人员通过sendDelayedEvent(topic, event, delayLevel)接口选择预设延迟等级 延迟等级对应Kafka分区/topic(如等级1→1s分区),需与配置的等级匹配。 开发人员 高 MQE-03-0012 EventCenter自动根据延迟等级将消息发送至对应分区/topic(如topic-delay-5s) 分区/topic提前创建(需满足Kafka分区数≥最大等级数)。 运维人员 高 MQE-03-0013 转发任务暂停消费 消费者通过pause()暂停分区消费,避免提前拉取未到期消息。 系统 高 MQE-03-0014 根据当前时间恢复相应转发任务的消费(如5秒后恢复对应topic-delay-5s分区的转发任务) 恢复逻辑通过resume()接口实现,触发消息消费。 系统 高 目前根据调研结果,我的选型是kafka分区延迟方案,不用引入外部组件,吞吐量大,缺点是延时等级固定。备选是Redis Zset方案,可以提供自定义延迟时间的功能,但是主要的缺点是要引入redis。(具体方案还需要考虑业务延迟队列在业务中使用次数,在业务中有无需要自定义延迟时间的需求)。 补充:关于kafka分区策略选用的说明:可以选用分多个topic或多个分区: 每个延时等级对应1个Topic 优点:高隔离性:不同延时等级的消息完全隔离在独立Topic中,某等级的消息堆积、故障不会影响其他等级(如1s延时的高并发消息不会占用2h延时的资源)。配置灵活性:每个Topic可独立设置参数。消费逻辑简单:转发任务可直接订阅对应Topic,无需额外过滤或映射。扩展性强:新增延时等级时只需创建新Topic,不影响现有系统。 缺点:资源消耗大:每个Topic需占用Broker的元数据存储、文件句柄、网络连接等资源,18个Topic的资源开销远高于1个Topic(尤其是每个Topic配置多分区时)。管理复杂度高:需单独监控、运维18个Topic,增加管理负担。 每个延时任务对应一个分区:为了避免轮询定时任务的出现,依旧需要对应分区数的消费者分别订阅每一个分区 优点:资源利用率高:所有延时等级的消息共享1个Topic的资源,大幅降低资源消耗。管理简单:仅需维护1个Topic,监控、配置、故障排查更高效。 缺点:隔离性弱:所有延时等级共享Topic的配置;配置灵活性低:无法针对单个延时等级调整参数;扩展性受限:新增延时等级需扩容Topic的分区数,虽Kafka支持动态扩容,但会影响现有消费者的分区分配,且需维护“分区→延时等级”的映射表。 目前是打算选用多个topic,隔离性高,容错性好,避免可能的故障影响,而且更好应对更好的不同延迟级别流量不均衡的情况。(可以考虑将比较少使用的几个延迟等级放到1个topic多个分区里)。 3.5 功能模块4:监控与告警模块(模块编号04) 需求编号 需求说明 需求限制/背景 关联主体 优先级 MQE-04-0001 监控死信Topic堆积量(按Topic统计) 运维人员订阅死信topic查看,记录死信堆积量。 运维人员 高 MQE-04-0002 统计延迟消息触发成功率(成功数/总到期数) 支持开发人员评估方案效果。基于Redis ZSet方案统计延迟消息触发成功率,如通过Redis计数器实现 开发人员 中 4.    非功能性需求 4.1.  UI需求 无独立UI需求 4.2.  模块接口需求 接口名称 交互模块 接口描述 enableDeadLetter(topic, enable) EventCenter 开发人员调用,启用/禁用指定Topic的死信队列(低侵入,不修改原生send()逻辑)。 setRetryCount(topic, count) EventCenter 开发人员调用,重试次数设置(默认为3次) setRetryPolicy(topic, policy) EventCenter 开发人员调用,重试策略设置(默认为指数退避) sendDelayedEvent(topic, event, delayS) EventCenter 开发人员调用,发送Redis ZSet方案的延迟消息(兼容原生send()的序列化配置)。 sendDelayedEvent(topic, event, delayLevel) EventCenter 开发人员调用,发送kafka分区方案的延迟消息(自动路由至对应分区)。 补充,针对死信配置,可以不调用死信接口,可以通过重载send方法(例如,补充参数死信开关,死信配置等)或者通过配置文件(在死信配置类上添加@ConfigurationProperties(prefix = "eventcenter.deadletter")注解)。(同理可以包装handler,重载register方法)以方便开发人员调用为原则。 4.3.  性能需求 功能点 性能指标 死信消息处理 并发处理能力≥1000条/秒(单消费者组),响应时间≤200ms(不影响主消费流程)。 Redis ZSet延迟消息方案(备选方案) 扫描间隔误差≤1秒(1秒间隔场景),单线程扫描最大处理1000条/次(可配置)。 kafka分区延迟消息方案 分区恢复延迟≤500ms(确保到期消息及时消费),支持18个预设等级 4.4.  用户体验需求 开发人员调用扩展接口 :接口文档完整率100%,示例代码覆盖90%以上常用场景(如死信启用、延迟发送)。 4.5. 用户技术支持需求 支持项 描述 死信消息追溯 运维人员支持通过消息ID查询原消息内容、异常堆栈、重试记录。 告警日志导出 支持导出一定时间内的告警记录(含触发时间、处理人、解决方案),用于复盘优化。 4.6 单元测试覆盖率 模块 覆盖率目标 说明 配置管理模块 80% 覆盖配置解析、接口调用校验逻辑。 死信处理模块 80% 覆盖拦截器逻辑、重试策略、死信发送等核心流程。模拟消费失败场景,验证重试次数、死信消息是否包含完整上下文。 延迟消息管理模块 80% 覆盖ZSet操作/分区分桶路由、扫描触发等关键逻辑。测试不同延迟时间的消息是否准时触发,Redis扫描间隔配置是否生效。 5.    可行性分析 开发任务 需求编号范围 难度 优先级 影响范围 配置管理模块开发 MQE-01-0001~0004 中 高 EventCenter接口层。 死信处理模块开发 MQE-02-0001~0006 高 高 Kafka消费者拦截器、EventCenter事件上下文。 延迟消息管理模块开发 MQE-03-0001~0004(备选)、MQE-03-0011~0014 高 高 Redis客户端(备选)、Kafka分区路由逻辑、EventCentersend()接口扩展。 监控与告警模块开发 MQE-04-0001~0002 低 中 死信队列消费者。 说明: 核心功能(死信处理、延迟消息管理)需优先实现,确保解决设备删除数据不一致、消费失败丢失问题。 低侵入性设计通过接口扩展实现(如拦截器、sendDelayedEvent()),避免修改EventCenter原生代码(如send()、registerBroadcast()的核心逻辑)。需求分析报告如上,请按以下评审意见修改延迟队列通过Redis Zset方案实现的可用性分析 补充选取18个延迟分区的理由 补充VMS业务分析,尤其是可能和延迟队列相关的业务 死信消息发送至死信队列失败后需要提供配置选项,方便业务人员调用,失败后进行什么处理(比如告警,记录日志),需要设置默认值 需求分析内容过多,将设计的部分移到概要设计中,需求分析保留调研方案 整理需要提供哪些新的接口,哪些方法重载了,需要写完善 需求分析4.3节性能需求进行修改 支持延迟队列配置调整,新增强制延迟时间和非强制延迟时间,强制延迟时间对应目标分区方案, 只有强制延迟时间发送失败才抛异常 某些业务不需要精确延时,只需要延迟一定时间, 支持非强制延迟时间策略配置(如向上/向下取整,四舍五入方案) 分离强制延迟时间性能指标和非强制延迟时间性能指标,分别计算 结合实际业务申请topic方式,kafka采用分级延迟topic而不是延迟分区 结合实际业务申请topic方式,死信topic应修改为不支持开发人员配置 补充内容:未发现对应死信topic创建应该告警 补充死信队列延迟队列的local版本实现,使需求分析和概要设计文档完整 补充压力测试模块数据和环境 尽量接入VMS Event模块,测试中设计死信注入故障(例如:模拟消费者崩掉的场景) Yu He 概要设计中压力测试部分,消息压力量设计偏小,进行修改 ;评审意见中有概要设计的部分,暂时先不用给出结果,先按照评审意见对需求分析进行修改
09-27
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值