一、业务背景与原有问题
目前CRM订单中心按照产品类型分为 C网(CDMA)订单、宽带订单、其他产品订单。原有竣工任务采用定时任务轮询数据库的方式拉取待竣工工单,长期存在任务积压、处理不及时的问题,导致用户订单迟迟无法竣工,进而产生额外资费费用,影响业务与用户体验。
原有架构存在以下核心问题:
数据库压力大:定时任务高频全表轮询查询待竣工数据,大量无效DB查询,占用CPU、IO资源。
无任务优先级机制:CDMA高优订单、普通宽带订单、批量订单混排处理,高优先级工单被低优先级任务阻塞,导致C网订单大量积压。
线程模型固化,扩展性差:竣工处理线程固定,无法动态扩容,高并发场景容易出现线程阻塞、任务堆积,甚至数据库死锁问题。
失败任务不可控:工单竣工失败后无规范重试策略,容易产生僵尸任务、无效重复执行,加重系统负担。
二、优化整体思路
整体架构从定时轮询拉取模式升级为RabbitMQ事件驱动模式,通过多优先级队列任务隔离、动态线程池调度、分级重试机制、人工兜底机制,解决竣工积压、处理延迟、DB压力大、任务死锁等问题。
核心优化思想:推拉结合、分层隔离、多级容错、弹性扩容、故障自治。通过事件驱动解耦业务流程与竣工流程,基于业务优先级做物理资源隔离,针对正常业务失败、MQ中间件异常、分布式数据不一致做分层兜底,同时配套线程池隔离、幂等防重、重试限流、故障冻结等工程化能力,彻底解决原有架构吞吐低、优先级失效、容错缺失、DB压力大、易死锁等稳定性问题。
三、核心数据表设计
优化后沿用四张核心业务表,实现工单流程、归档、错误追溯全覆盖:
订单表:存储CRM各类订单基础信息,区分C网、宽带、批量等订单类型。
竣工表:存储待竣工工单核心数据,记录工单待处理状态。
竣工历史表:存储所有竣工成功的工单数据,用于数据归档、业务溯源。
竣工错误信息表:存储竣工失败的工单、错误原因、失败次数、下次重试时间,用于后续重试调度。
四、MQ优先级队列设计
为解决不同类型订单的优先级差异,规避高低优任务抢占资源问题,系统拆分三级物理隔离队列,彻底避免任务阻塞:
最高优先级队列(CDMA订单):保障C网订单优先处理,杜绝用户产生额外资费,保障核心业务体验。
普通优先级队列(前台宽带订单):处理常规用户前台下单的宽带类竣工工单。
最低优先级队列(批量订单):处理后台大批量批量工单,延迟容忍度高,不抢占核心用户资源。
通过物理队列隔离,替代单队列优先级配置,彻底解决队列头部阻塞问题,保证高优任务实时优先消费。
五、完整优化后业务流程
1. 订单流程完结,事件触发投递
当订单前置业务流程全部执行完成后,系统首先写入竣工表,生成待竣工工单,同时根据订单类型,将竣工消息异步投递至对应优先级的RabbitMQ队列中。
该步骤彻底摒弃原有的定时轮询机制,实现有任务才处理,无任务不查库,大幅降低数据库查询压力。
2. 队列监听 + 动态线程池处理
系统对三级优先级队列采用业务队列+死信队列双线程池隔离架构,每类业务队列绑定独立的动态可配置线程池,正常消费与异常重试线程池完全物理隔离,避免故障扩散。线程池核心参数支持Nacos动态热更新,可根据业务峰值弹性扩缩容,实现流量与故障的双层隔离:
高优CDMA队列:分配最大线程资源、最高执行权重,保障核心用户工单优先抢占资源,杜绝资费积压问题。
普通宽带队列:分配中等固定资源,保障日常业务平稳吞吐。
批量订单队列:资源配额最小,严格限流、限制堆积长度,避免大批量低优任务挤占核心业务资源。
死信独立线程池:三类死信队列共用隔离重试线程池,限制最大并发数,防止异常重试引发消息雪崩。
3. 竣工结果数据落地
消费者获取工单后,首先基于工单唯一单号+业务状态机做幂等判断,规避MQ重投、重试补偿、定时巡检重推导致的重复消费问题,严格保证一个工单仅被处理一次。根据竣工执行结果做分层数据落地:
竣工成功:更新竣工表状态为已完成,同步写入竣工历史表归档,完成工单闭环。
竣工失败:记录详细报错信息、失败次数、当前时间,写入竣工错误信息表,不立即重试,避免无效刷屏。
4. 分级退避重试机制(解决僵尸任务)
为彻底解决MQ节点异常、网络抖动、消息丢失、消费卡死等中间级异常导致的工单悬空积压问题,同时兼顾业务轻量化、高可用的设计原则,本次优化采用「死信队列DLQ为主、竣工表低频巡检为辅」的双层兜底方案。主力依靠RabbitMQ死信机制解决绝大多数消息异常场景,利用竣工表数据量小、无性能压力的特性,增加极低频率定时巡检作为最终二道兜底,架构标准、容错全面、无过度设计。
整体异常重试与兜底机制分为三层,精准覆盖业务执行失败、消费异常、消息丢失、极端数据不一致等全场景问题:
第一类:业务执行失败工单——错误表梯度退避重试
工单正常投递、正常消费,但因业务参数非法、上游接口抖动、业务幂等拦截等可重试业务异常导致竣工失败。系统自动写入竣工错误信息表,记录完整堆栈、失败次数、梯度重试时间。采用指数退避重试策略,失败次数越少重试越及时,失败次数越多重试间隔越长,避免无效频繁重试打垮下游依赖。同时设置最大重试阈值,超过阈值的异常工单自动冻结,不再自动重试,转为人工运维介入,彻底杜绝永久僵尸任务循环执行。
第二类:消费异常、消息超时、消费宕机——死信队列DLQ主力兜底
为三级业务队列各自绑定独立死信队列,形成一对一隔离重试体系。针对消费者宕机、消费超时、业务主动NACK、消息过期、重试次数耗尽等中间件级异常,消息自动流转至对应死信队列,实现消息不丢失、不悬空。系统独立监听死信队列,统一完成异常工单的重试补偿,作为99%消息异常的核心兜底方案,同时依托独立重试线程池限流,避免重试流量冲击核心业务。
第三类:极端分布式数据不一致——竣工表低频巡检二道兜底
针对极低概率的生产者投递宕机、网络断连导致消息未落库极端场景,会产生仅有竣工表记录、无MQ消息、无错误日志的悬空工单,死信机制无法捕获。依托竣工表仅留存待处理、异常工单、数据体量极小的业务特性,配置极低频率的状态巡检任务。采用差异化超时策略:CDMA短超时、普通工单中超时、批量工单长超时,精准区分正常慢任务与异常滞留任务,筛选超期未完结工单二次补偿,作为全链路最终兜底。
三层机制层层递进:业务异常走梯度重试、消费异常走死信兜底、极端不一致走定时巡检,兼顾架构规范性、稳定性与业务落地性,彻底根治工单积压、消息丢失、僵尸数据问题。
整套容错体系分层清晰、各司其职:业务可重试失败走梯度退避、消费链路异常走死信队列自治、极端数据不一致走低频巡检兜底。架构不过度设计,同时兼顾标准性、稳定性和业务落地性,彻底解决消息丢失、工单积压、僵尸数据、重复执行等分布式常见问题。
5. 人工兜底补偿机制
系统提供可视化手动竣工运维界面,作为极端场景兜底方案:
应对消息丢失、数据异常、特殊工单报错等线上未知问题;
支持手动触发竣工、手动重试异常工单、手动归档完结任务;
保障整个竣工流程无单点故障,业务百分百可兜底。
六、优化收益总结
降低数据库压力:由定时轮询改为事件驱动,消除大量无效全表查询。
解决高优订单积压:队列物理隔离+资源倾斜,保障CDMA核心订单优先竣工,避免用户额外扣费。
高可用、高容错、故障隔离:通过业务队列与死信队列线程池物理隔离、三级业务资源配额隔离,实现故障不扩散;结合状态机幂等、最大重试冻结、差异化超时巡检,彻底解决重复消费、消息雪崩、僵尸任务问题。
全链路可追溯、可运维、可兜底:四张业务表实现全流程数据溯源,自动容错+人工兜底双机制,保障极端场景业务不中断,满足生产高可用标准。
分布式数据一致性闭环:构建「业务梯度重试+死信队列自治+低频状态巡检」三层容错模型,全覆盖业务异常、中间件异常、分布式数据不一致场景,是典型的最终一致性落地实践。