Kafka异常重试方案小记
背景
在最近进行的项目架构升级中,我们对原有的核心项目结构进行了细致的拆分。
现在,核心项目与非核心项目之间的通信和数据交换主要通过Kafka这一中间件来实现。
这种设计主要体现在核心项目向非核心项目发送通知,这些通知大致可以分为三个主要类别:
- 在设备租借流程中,订单状态发生变化时需要进行的额外业务处理,这是我们所说的核心消息
- 与用户相关的各类消息。
- 设备的心跳信号以及业务数据的上报消息。

针对这三类关键消息,从业务连续性和数据完整性的角度来看,我们的目标是确保它们的传递尽可能不受损失。如果出现异常情况,系统应自动触发重试机制,以保障消息的送达。同时,任何消息消费过程中的异常都不应影响到后续业务流程的执行,否则可能会对整个业务造成不利影响。
鉴于该项目已经在使用Kafka作为消息传递的基础设施,我们决定在当前场景下不更换为RocketMQ,尽管后者在某些方面可能更适合我们的需求。这一决定是基于对现有系统的依赖和对迁移成本的考虑,旨在保持系统的稳定性和减少不必要的复杂性。
死信队列:由于某些原因消息无法被正确的投递,为了确保消息不会被无故丢地丢弃,一般将其置于一个特殊角色的队列,这个队列一般称为死信队列。
后续分析程序可以通过消费这个死信队列中的内容来分析当时遇到的异常情况,进而可以改善优化系统。
看完这段介绍,死信队列简直就是我们当下最所需的功能,而对于RabbitMQ、RocketMQ来说,死信消息一般通过 broker 存入,
而在kafka中原本并无死信队列的概念,所以当需要自行封装这一层概念的时候,就可以脱离既定思维的约束,
根据应用情况选择合适的实现方式,理解死信的本质进而懂得如何实现死信队列的功能。
在实践中,我们对消息队列(MQ)的业务期望如下:
- 异常消费后的重试机制
我们期望在消息消费过程中遇到异常时,系统能够自动进行重试,确保消息的可靠性。目前,Spring Kafka已经提供了异常重试的支持,并且能够在达到最大重试次数后将消息写入死信队列,以便于后续处理。
为了进一步增强异常处理能力,我们可以通过自行编码,在消费异常时将相关信息写入日志,或者在消费后立即写入消息,待后续消费成功后再更新其状态。 - 异常消费与正常消费的隔离
我们希望异常消费不会影响其他业务的正常进行。为此,MQ中的三类消息应该各自独立处理,互不干扰。这里可以采用线程池技术,为不同类型的消息分配专门的处理线程,从而实现并行处理和隔离。 - 发版期间的消息可靠性
在发版期间,我们要求消息传递的高可靠性,确保消息不会丢失。为此,我们可以配置消费线程池的优雅停止机制,通过设置有限的等待时间来尽可能保证消息被完全消费。虽然这种方式无法100%保证所有消息都能在停止前消费完毕,但它可以在一定程度上减少消息丢失的风险。
在进行技术选型时,我们考虑了以下方案:
- 自动提交与手动提交:
我们选择了自动提交模式,并将其时间间隔设置为30秒。这样做允许在发生异常或宕机后出现重复消费的情况,但需要业务逻辑自身实现幂等性以保证数据的一致性。 - Spring Kafka的使用:
由于选择了自动提交,我们发现Sp
ring Kafka中的重试机制缺乏持久化支持。这可能导致在发版过程中丢失消息,因此我们决定不采用这一方案。 - 重平衡期间的消息丢失问题:
为了解决重平衡期间可能出现的消息丢失问题,我们计划引入JVM钩子,在发版时对当前工作线程池中的消息进行快照,并在后续重新推送这些消息。 - 本地消息处理:
我们不采用在消息消费之初立即落库,在消费后修改状态的做法,以此减少对数据库的压力。
在消费异常时,我们选择将消息落库,而在消费成功时则不进行写入。虽然在极端情况下这可能导致消息丢失,但对于这种极端情况业务层面是可以接受的。 - 业务之间的隔离:
为了确保不同业务之间的相互独立性,我们将为三大类业务各自配置独立的线程池。如果某类业务的事件量特别大,我们还会考虑为其单独配置线程池,以实现更好的资源隔离和处理效率。
消费流程图

我们的最终技术方案如下:
- Kafka自动提交设置:
我们将Kafka的自动提交间隔设定为30秒,这有助于在发生异常或服务重启时减少消息的重复处理。 - 异常处理机制:
当工作线程在消费消息时遇到异常,系统将会自动记录这些异常信息到本地日志中。这些日志将用于后续的消息重推操作。此外,我们增加了一个Web端的手动重推功能,以便于在需要时手动触发消息的重新处理,若后续异常消息多时可以考虑自动的定时调度。 - 线程池的优雅关闭:
为了确保在服务停止时已拉取的消息能够被完全消费,我们配置了工作线程池的优雅关闭机制。在JVM关闭钩子执行时,系统将等待30到60秒,以确保当前已拉取的消息能够被完全消费。在此期间,系统将快照当前工作线程池队列中的所有消息,以便在必要时进行恢复。 - 双重保障机制:
为了提供额外的保障,我们在JVM关闭钩子执行时再次快照工作线程池队列中的所有消息。这一双重快照机制确保了即使在极端情况下,消息也不会丢失,从而保障了系统的高可靠性和数据的完整性。
写到最后
通过这些细致的技术选型和策略,我们旨在构建一个既高效又稳定的系统,以支持业务的持续发展和创新。
相关文章:
Kafka异常重试方案小记
背景 在最近进行的项目架构升级中,我们对原有的核心项目结构进行了细致的拆分。 现在,核心项目与非核心项目之间的通信和数据交换主要通过Kafka这一中间件来实现。 这种设计主要体现在核心项目向非核心项目发送通知,这些通知大致可以分为三个…...
非页面缓冲池占用过高处理方法
1.现象 电脑变莫名其妙得特别卡,明明16G的内存,理论上日常使用,打游戏之类的使用起来完全不会有什么大问题,但是实际使用却是卡的要死。 下面开始查找原因。 2.查找原因 使用win自带的任务管理器,可以看到日常内存…...
【Linux】进程信号(下)
目录 一、信号的阻塞 1.1 信号在内核中的保存方式 1.2 sigset_t信号集 (1)信号集操作 (2)sigprocmask函数 (3)sigpending函数 二、信号的处理 2.1 用户态和内核态 2.2 重谈进程地址空间 三、信号…...
FlinkCDC 实现 MySQL 数据变更实时同步
文章目录 1、基本介绍2、代码实战2.1、数据源准备2.2、代码实战2.3、数据格式 1、基本介绍 Flink CDC 是 Apache Flink 提供的一个功能强大的组件,用于实时捕获和处理数据库中的数据变更。可以实时地从各种数据库(如MySQL、PostgreSQL、Oracle、MongoDB…...
JavaWeb——Maven(4/8):Maven坐标,idea集成-导入maven项目(两种方式)
目录 Maven坐标 导入Maven项目 第一种方式 第二种方式 Maven坐标 Maven 坐标 是 Maven 当中资源的唯一标识。通过这个坐标,我们就能够唯一定位资源的位置。 Maven 坐标主要用在两个地方。第一个地方:我们可以使用坐标来定义项目。第二个地方&#…...
实现uniapp天地图边界范围覆盖
在uniapp中,难免会遇到使用地图展示的功能,但是百度谷歌这些收费的显然对于大部分开源节流的开发者是不愿意接受的,所以天地图则是最佳选择。 此篇文章,详细的实现地图展示功能,并且可以自定义容器宽高,还可…...
思科网络设备命令
一、交换机巡检命令 接口和流量状态 show interface stats:查看所有接口当前流量。show interface summary:查看所有接口当前状态和流量。show interface status:查看接口状态及可能的错误。show interface | include errors | FastEthernet …...
Egg.js使用ejs快速自动生成resetful风格的CRUD接口
目前的插件能够自动生成egg的crud的都不太好用 我们自己写一个吧 ejs模块 也方便定制 安装依赖 npm install ejs --save ejs 是一个简单易用的模板引擎,常用于 Node.js 应用程序中 在项目根目录下创建 template/controller.ejs 模板文件 use strict;const Co…...
自动化抖音点赞取消脚本批量处理
🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 &#x…...
基于YOLOv8深度学习的智能车牌检测与识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战
背景及意义 智能车牌检测与识别系统通过使用最新的YOLOv8与PaddleOCR算法能够迅速、准确地在多种环境下实现实时车牌的检测和识别。本文基于YOLOv8深度学习框架,通过16770张图片,训练了一个进行车牌检测模型,可以检测蓝牌与绿牌,然后对检测到的车牌使用O…...
qt QGraphicsGridLayout详解
一、概述 QGraphicsGridLayout是Qt框架中用于在QGraphicsScene中布置图形项的一个布局管理器。它类似于QWidget中的QGridLayout,但主要处理的是QGraphicsItem和QGraphicsWidget等图形项。通过合理设置网格位置、伸缩因子和尺寸,可以实现复杂而灵活的布局…...
数字处理系列
(1)将数字转化成中文的过滤器 <template><div><p>数字转中文:{{ 110 | numberToChinese }}</p></div></template><script>export default {filters: {numberToChinese(num) {const chineseNums …...
基于开源Jetlinks物联网平台协议包-MQTT自定义主题数据的编解码
目录 前言 1.下载官方协议包 2.解压 3.自定义主题 4.重写解码方法 5.以下是我解析后接收到的数据 前言 最近这段时间,一直在用开源的Jetlinks物联网平台在学习,偶尔有一次机会接触到物联网设备对接,在协议对接的时候,遇到了…...
【Python】Python2.7升级Python3
需求背景 服务是跑在docker的容器里的,因此要新建image依赖环境是Ubuntu,老的是16.4。 步骤 先准备环境,因为只有你的环境上去了,运行代码的时候才会报错,这样才会把需要改的代码暴露出来。 python3.5目前也是被遗弃的…...
Python 内置函数 round() 详解
在 Python 编程中,round() 函数是一个非常实用的内置函数,用于对数字进行四舍五入。无论是在数据处理、财务计算还是科学计算中,round() 函数都能帮助我们得到所需的精确值。本文将详细介绍 round() 函数的用法和注意事项。 1. round() 函数…...
JavaScript入门中-流程控制语句
本文转载自:https://fangcaicoding.cn/article/52 大家好!我是方才,目前是8人后端研发团队的负责人,拥有6年后端经验&3年团队管理经验,截止目前面试过近200位候选人,主导过单表上10亿、累计上100亿数据…...
kconfig语法(一)
一、安装Kconfiglib python -m pip install windows-curses python -m pip install kconfiglib二、使用样例 ①创建kconfig文件。 ②在kconfig文件添加内容: config KCONFIG_DEMO_ITEM1boolprompt "demonstate item1 for bool learning"config KCONFIG_DEMO_ITE…...
十七、行为型(命令模式)
命令模式(Command Pattern) 概念 命令模式是一种行为型设计模式,它将请求封装成一个对象,从而使您可以使用不同的请求对客户进行参数化,排队请求,以及支持可撤销操作。通过这种模式,调用操作的…...
原材料供应商的GRS认证证书过期了怎么办?
在全球纺织和时尚产业中,GRS(Global Recycle Standard,全球再生标准)认证已成为衡量企业环保和可持续发展的重要指标。然而,当原材料供应商的GRS认证证书过期时,企业需迅速采取行动,以确保供应链…...
C++编程:实现一个基于原始指针的环形缓冲区(RingBuffer)缓存串口数据
文章目录 0. 引言1. 使用示例2. 流程图2.1 追加数据流程2.2 获取空闲块流程2.3 处理特殊字符流程2.4 释放块流程2.5 获取下一个使用块流程 3. 代码详解3.1 Block 结构体3.2 RingBuffer 类3.3 主要方法解析append 方法currentUsed 和 currentUsing 方法release 方法nextUsed 方法…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
NPOI Excel用OLE对象的形式插入文件附件以及插入图片
static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...
第7篇:中间件全链路监控与 SQL 性能分析实践
7.1 章节导读 在构建数据库中间件的过程中,可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中,必须做到: 🔍 追踪每一条 SQL 的生命周期(从入口到数据库执行)&#…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
