Kafka(Go)教程(九)---如何避免消息丢失?

Go 操作 Kafka 如何保证无消息丢失 背景目前一些互联网公司会使用消息队列来做核心业务,因为是核心业务,所以对数据的最后一致性比较敏感,如果中间出现数据丢失,就会引来用户的投诉,年底绩效就变成325了。之前和几个朋友聊天,他们的公司都在用 kafka 来做消息队列,使用 kafka 到底会不会丢消息呢?如果丢消息了该怎么做好补偿措施呢?本文我们就一起来分析一下,并介绍如何使用 Go 操作 Kafka 可以不丢失数据。本文操作 kafk... 阅读详情

来自:指月 https://www.lixueduan.com

原文:https://www.lixueduan.com/post/kafka/09-avoid-msg-lost/

本文主要从 Producer、Broker、Consumer 等 3 个方面分析了 Kafka 应该如何配置才能避免消息丢失。

Kakfa 相关代码见 Github

1. 概述

在使用 MQ 的时候最大的问题就是消息丢失,常见的丢失情况如下:

  • 1)Producer 端丢失
  • 2)Broker 端丢失
  • 3)Consumer 端丢失

一条消息从生产到消费一共要经过以下 3 个流程:

  • 1)Producer 发送到 Broker
  • 2)Broker 保存消息(持久化)
  • 3)Consumer 消费消息

3 个步骤分别对应了上述的 3 种消息丢失场景。

接下来以 Kafka 为例分析该如何避免这些问题。

2. Kafka 消息持久化保障

一句话概括,Kafka 只对“已提交”的消息(committed message)做有限度的持久化保证。

其他 MQ 也类似。

第一个核心要素是已提交的消息。

什么是已提交的消息?当 Kafka 的若干个 Broker 成功地接收到一条消息并写入到日志文件后,它们会告诉生产者程序这条消息已成功提交。此时,这条消息在 Kafka 看来就正式变为“已提交”消息了。

那为什么是若干个 Broker 呢?这取决于你对“已提交”的定义。你可以选择只要有一个 Broker 成功保存该消息就算是已提交,也可以是令所有 Broker 都成功保存该消息才算是已提交。不论哪种情况,Kafka 只对已提交的消息做持久化保证这件事情是不变的。

第二个核心要素就是有限度的持久化保证。

也就是说 Kafka 不可能保证在任何情况下都做到不丢失消息。

举个极端点的例子,如果地球都不存在了,Kafka 还能保存任何消息吗?显然不能!

有限度其实就是说 Kafka 不丢消息是有前提条件的。假如你的消息保存在 N 个 Kafka Broker 上,那么这个前提条件就是这 N 个 Broker 中至少有 1 个存活。只要这个条件成立,Kafka 就能保证你的这条消息永远不会丢失。

3. 具体场景分析

3.1 Producer 端丢失

Producer 端丢消息更多是因为消息根本没有提交到 Kafka。

目前 Kafka Producer 是异步发送消息的,也就是说如果你调用的是 producer.send(msg) 这个 API,那么它通常会立即返回,但此时你不能认为消息发送已成功完成。

这种发送方式有个有趣的名字,叫“fire and forget”,翻译一下就是“发射后不管”。如果出现消息丢失,我们是无法知晓的。这个发送方式挺不靠谱,非常不建议使用。

导致消息没有发送成功的因素也有很多:

  • 1)例如网络抖动,导致消息压根就没有发送到 Broker 端;
  • 2)或者消息本身不合格导致 Broker 拒绝接收(比如消息太大了,超过了 Broker 的承受能力)等。

Kafka 不认为消息是已提交的,因此也就没有 Kafka 丢失消息这一说了。

解决方案也很简单:Producer 永远要使用带有回调通知的发送 API,也就是说不要使用 producer.send(msg),而要使用 producer.send(msg, callback)。

通过回调,一旦出现消息提交失败的情况,你就可以有针对性地进行处理。

举例来说:

  • 如果是因为那些瞬时错误,那么仅仅让 Producer 重试就可以了;
  • 如果是消息不合格造成的,那么可以调整消息格式后再次发送。

总之,处理发送失败的责任在 Producer 端而非 Broker 端。

3.2 Broker 端丢失

Broker 丢失消息是由 Kafka 自身原因造成的。Kafka 为了提高吞吐量和性能,采用异步批量的刷盘策略,也就是按照一定的消息量和间隔时间进行刷盘。

Broker 端丢失消息才真的是因为 Kafka 造成的。

Kafka 收到消息后会先存储在也缓存中(Page Cache)中,之后由操作系统根据自己的策略进行刷盘或者通过 fsync 命令强制刷盘。如果系统挂掉,在 PageCache 中的数据就会丢失。

Kafka没有提供同步刷盘的方式,也就是说单个 Broker 丢失消息是必定会出现的。

为了解决单个 broker 数据丢失问题,Kafka 通过 producer 和 broker 协同处理单个 broker 丢失参数的情况:

  • acks=0,producer 不等待 broker 的响应,效率最高,但是消息很可能会丢。
  • acks=1,leader broker 收到消息后,不等待其他 follower 的响应,即返回 ack。也可以理解为 ack 数为1。
    • 此时,如果 follower 还没有收到 leader 同步的消息 leader 就挂了,那么消息会丢失。
  • acks=-1(-1等效于all),leader broker 收到消息后,挂起,等待所有 ISR 列表中的 follower 返回结果后,再返回 ack。
    • 这种配置下,如果 Leader 刚收到消息就断电,producer 可以知道消息没有被发送成功,将会重新发送。
    • 如果在 follower 收到数据以后,成功返回 ack,leader 断电,数据将存在于原来的 follower 中。在重新选举以后,新的leader 会持有该部分数据。

在配置为 all 或者 -1 的时候,只要 Producer 收到 Broker 的响应就可以理解为消息已经持久化了。

虽然可能只是刚写入了 PageCache,但是刷盘也就是迟早的事,除非刚好刷盘之前多个 Broker 同时挂了,那确实是没办法了。

建议根据实际情况设置:

  • 如果要严格保证消息不丢失,请设置为 all 或 -1;
  • 如果允许存在丢失,建议设置为 1;
  • 一般不建议设为 0,除非无所谓消息丢不丢失。

3.3 Consumer 端丢失

Consumer 端丢失数据主要体现在 Consumer 端要消费的消息不见了。

出现该情况的唯一原因就是:Consumer 没有正确消费消息,就把位移提交了,导致 Kafka 认为该消息已经被消费了,从而导致消息丢失。

可以看出这其实也不是 Kafka 的问题,毕竟 Kafka 也不知道究竟消费没有,只能以 Consumer 提交的位移为依据。

场景1:获取到消息后直接提交位移了,然后再处理消息。

这样在提交位移后,处理完消息前,如果程序挂掉,这部分消息就算是丢失了。

场景2:多线程并发消费消息,且开启了自动提交,导致消费完成之前程序就自动提交了位移,如果程序挂掉也会出现消息丢失。

解决方案也很简单:确定消费完成后才提交消息,如果是多线程异步处理消费消息,Consumer 程序不要开启自动提交位移,而是要应用程序手动提交位移。

4. 最佳实践

以下为一些常见的 Kafka 无消息丢失的配置:

避免 Producer 端丢失

  • 1)不要使用 producer.send(msg),而要使用 producer.send(msg, callback)。记住,一定要使用带有回调通知的 send 方法。
  • 2)设置 retries 为一个较大的值。这里的 retries 同样是 Producer 的参数,对应前面提到的 Producer 自动重试。当出现网络的瞬时抖动时,消息发送可能会失败,此时配置了 retries > 0 的 Producer 能够自动重试消息发送,避免消息丢失。

避免 Broker 端丢失

  • 3)设置 acks = all。acks 是 Producer 的一个参数,代表了你对“已提交”消息的定义。如果设置成 all,则表明所有副本 Broker 都要接收到消息,该消息才算是“已提交”。这是最高等级的“已提交”定义。
  • 4)设置 unclean.leader.election.enable = false。这是 Broker 端的参数,它控制的是哪些 Broker 有资格竞选分区的 Leader。如果一个 Broker 落后原先的 Leader 太多,那么它一旦成为新的 Leader,必然会造成消息的丢失。故一般都要将该参数设置成 false,即不允许这种情况的发生。
  • 5)设置 replication.factor >= 3。这也是 Broker 端的参数。其实这里想表述的是,最好将消息多保存几份,毕竟目前防止消息丢失的主要机制就是冗余。
  • 6)设置 min.insync.replicas > 1。这依然是 Broker 端参数,控制的是消息至少要被写入到多少个副本才算是“已提交”。设置成大于 1 可以提升消息持久性。在实际环境中千万不要使用默认值 1。
  • 7)确保 replication.factor > min.insync.replicas。如果两者相等,那么只要有一个副本挂机,整个分区就无法正常工作了。我们不仅要改善消息的持久性,防止数据丢失,还要在不降低可用性的基础上完成。推荐设置成 replication.factor = min.insync.replicas + 1。

避免 Consumer 端丢失

  • 8)确保消息消费完成再提交。Consumer 端有个参数 enable.auto.commit,最好把它设置成 false,并采用手动提交位移的方式。就像前面说的,这对于单 Consumer 多线程处理的场景而言是至关重要的。

5. 小结

Kakfa 相关代码见 Github

消息生命周期中的 3 个地方都可能会出现消息丢失情况:

  • 1)Producer 端:通过回调确保消息成功发送到 Kafka 了
  • 2)Broker 端:通过多 Broker 以及 Producer 端设置 acks=all 降低消息丢失概率
  • 3)Consumer 端:一定要在消息处理完成后再提交位移

需要应用程序和 Kafka 一起配合才能保证消息不丢失。

6. 参考

https://kafka.apache.org/documentation/#configuration

《Kafka 核心技术与实战》

Kafka 在 Golang 中的最佳实践:提升你的消息处理能力 Apache Kafka 作为分布式流处理平台,广泛应用于日志收集、事件驱动架构、微服务解耦等场景。Golang(简称 Go)凭借其高效的并发模型、简洁的语法和原生支持高性能网络编程的特性,成为 Kafka 客户端开发的理想选择。本文旨在通过系统化的技术解析,帮助开发者掌握在 Go 中使用 Kafka 的核心技术点,包括生产者配置、消费者组管理、消息可靠性保证、性能优化及常见问题处理。本文从基础概念入手,逐步深入到代码实现、性能优化和实战案例,最后提供工具资源和未来趋势分析。 阅读详情

相关推荐

Chipyard------介绍与环境搭建

Chipyard是一个开源的、可扩展的、集成化的芯片设计平台,旨在帮助芯片设计人员快速、高效地开发自己的定制芯片。由伯克利大学架构研究小组开发,它基于Chisel语言和Scala编程语言,提供了一整套硬件设计工具和流程,包括RTL设计、验证、物理布局、仿真等,以及支持多种芯片体系结构的库和模块。

qq_38798111的博客 9479

spring中kafka消息丢失问题(提供者、消费者)附解决方案

spring中kafka消息丢失(生产者、消费者)问题的解决

Dark_AK44的博客 4660

qcc51xx如何配置spdif输入

qcc51xx如何配置spdif输入。

Alex_886的博客 1375

kafka消息队列防止数据丢失、重复消费(幂等性)、顺序消费解决方案

Kafka 实际上有个 offset 的概念,就是每个消息写进去,都有一个 offset,代表消息的序号,然后 consumer 消费了数据之后,每隔一段时间(定时定期),会把自己消费过的消息的 offset 提交一下,表示“我已经消费过了,下次我要是重启啥的,你就让我继续从上次消费到的 offset 来继续消费吧”如果消费过了,那你就别处理了,保证别重复处理相同的消息即可。但是,我们在消费者里可能会搞。幂等性,通俗点说,就一个数据,或者一个请求,给你重复来多次,你得确保对应的数据是不会改变的,不能出错。

qq_32424581的博客 1070

Arcgis 10.3 与 ArcGIS Engine 10.3 安装与破解

Arcgis 10.3 与 ArcGIS Engine 10.3 安装与破解

weixin_52127098的博客 4726

医疗器械软件测试输出内容(1)

*单元测试(Unit Testing):**单元测试是软件测试的最底层,用于验证软件中最小的可测试单元——函数、方法或模块。系统测试是在集成测试之后进行的,它对整个系统进行测试,验证系统在不同部分集成在一起后是否满足需求和规格。: 集成测试是在单元测试之后进行的,它关注不同单元之间的交互和集成。对于不同安全级别的软件(IEC 62304 A类、B类、C类),在体系上要求输出的文件内容有所区别。**说明:**将集成测试和软件系统测试合并为一项单一的计划和一组活动是可接收的。

ct745363083的博客 1867

kafka数据丢失

消费端弄丢了数据 唯一可能导致消费者弄丢数据的情况,就是说,你那个消费到了这个消息,然后消费者那边自动提交了offset,让kafka以为你已经消费好了这个消息,其实你刚准备处理这个消息,你还没处理,你自己就挂了,此时这条消息就丢了。 这不是一样么,大家都知道kafka会自动提交offset,那么只要关闭自动提交offset,在处理完之后自己手动提交offset,就可以保证数据不会丢。但是此时确实...

weixin_43833048的博客 338

46、大数据助力SDN优化流量管理与控制器

本文探讨了大数据在软件定义网络(SDN)中的应用,重点分析了如何利用大数据技术优化SDN控制器的可扩展性和弹性。通过介绍SDN控制器的核心功能及其面临的挑战,提出了集中式、分布式、混合式和分层式控制器放置策略,并结合大数据分析系统架构与技术,详细阐述了在控制器放置优化、流聚合和备份路径识别等场景中的实际应用。文章还给出了大数据分析在SDN控制器优化中的操作流程与优势,展望了未来结合人工智能与物联网的发展方向,强调了数据安全与算法效率的重要性。

xx56789的博客 87

Kafka 的这 6 个场景会丢失消息

今天来聊一聊我们使用 Kafka 的时候,怎样能保证不丢失消息呢的话题。

hello.reader 1258

MATLAB代码实现了船舶航线优化的功能,使用混合遗传算法(结合模拟退火算法)来寻找从大连港到格拉斯通港的最优航线,同时考虑了船舶的参数、气象数据(风速、风向、有效波高、波浪阻力系数等)对航行的影响

这段MATLAB代码主要实现了船舶航线优化的功能,使用混合遗传算法(结合模拟退火算法)来寻找从大连港到格拉斯通港的最优航线,同时考虑了船舶的参数、气象数据(风速、风向、有效波高、波浪阻力系数等)对航行的影响。通过以上步骤,该代码能够找到一条在考虑船舶性能和气象条件下,从大连港到格拉斯通港的较优航线,最小化燃油消耗和航行时间的加权和。

AI的内部世界的博客 513

从零实现深度学习框架——理解正则化(一)

本文介绍解决过拟合与欠拟合的方法——正则化,主要介绍L1和L2正则化。

日积月累,天道酬勤 3394

kafka系列文章三(如何避免消息丢失)

前言 想必大家在实际使用过程都遇到过消息的丢失的问题,这里的消息丢失其实涉及到两个方面,一个是Producer生产的数据丢失,一个是Consumer消费的过程中因Offset问题而产生的漏消费。文章中我们会从这两个角度来和大家探讨如何尽量避免消息丢失的问题 避免Producer消息丢失 Kafka会对已提交的消息进行持久化存储,那么这里「已提交」的消息是什么意思呢?这里就得看Producer层面是如何定义消息是否发送成功了。所以接下来有两个比较重要的属性「RequiredAcks」,「Async」需要重点

qq_16077549的博客 2363

PX4从放弃到精通(三):使用qt编译PX4

1 下载px4源码 2在Firmware所在目录下执行 mkdir Firmware-build cd Firmware-build cmake …/Firmware -G “CodeBlocks - Unix Makefiles” -DCONFIG=nuttx_px4_fmu-v5_default 第三步最后的px4_fmu-v5_default根据自己的情况修改 执行完后如图 打开QT 点击打开工程 选择源码的CmakeLists.txt文件 选择imported Kit 打开项目那一栏,构建目

超维空间科技的博客 1万+

Go语言如何操纵Kafka保证无消息丢失

背景目前一些互联网公司会使用消息队列来做核心业务,因为是核心业务,所以对数据的最后一致性比较敏感,如果中间出现数据丢失,就会引来用户的投诉,年底绩效就变成325了。之前和几个朋友聊天,他们...

qq_39397165的博客 546

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Go语言高并发消费 Kafka 消息的最佳实践教程

在高并发且不允许消息堵塞的场景中,使用。

宋发元 2428

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

为什么你的Go Kafka程序丢消息了?深入底层原理排查真相

解决Go Kafka消息丢失难题,深入解析Go Kafka用法与底层原理。涵盖生产者确认机制、消费者提交策略及网络异常处理,适用于高并发场景。掌握关键配置与最佳实践,提升系统可靠性,值得收藏。

simcode的专栏 810

贝叶斯统计 [韦来生编]

贝叶斯(Bayes)统计是近几十年来迅速发展起来的数理统计的一个重要分支。贝叶斯方法与经典统计方法的主要不同之处是进行统计推断时除了利用样本信息外,还要利用参数的先验信息,因此可以提高统计推断或统计决策的效果。它在经济、金融、生物、医学、自然科学和社会科学等许多领域具有广泛的应用。贝叶斯方法的研究已渗透到了统计学的几乎所有领域。作者在给中国科学技术大学概率论与数理统计专业本科生开设的“数理统计”课程中有一章专门讲授“贝叶斯方法和统计决策理论”,近十年来也给中国科学技术大学概率统计专业研究生开设过几次“贝叶斯分析”课。本书是在对过去讲稿的内容作了适当的增减和调整的基础上完成的。  本书共分六章。第1章是绪论,介绍了贝叶斯统计的若干基本概念,同时对必要的数理统计的基础知识有重点地作了回顾。第二章介绍了确定先验分布的若干可供选择的方法。第三章介绍了几类常见统计模型参数的后验分布的主要结果和计算方法。第四章和第五章分别介绍了“贝叶斯统计推断”和“贝叶斯统计决策”的内容。第六章介绍了贝叶斯统计计算的若干方法,包括蒙特卡洛方法和马尔可夫链蒙特卡洛(MCMC)方法以及相关统计软件的简介。本书的每一章附右大量的例题和习题,书末附有常用的几个表格和部分习题解答供读者查用。  大约可在54学时内讲授本书的第1章至第六章的主要内容,教师可根据学时需要选讲本书第1章至第六章的部分内容。书中标“*”号的章节可略去不讲,留给读者作为阅读材料。第六章例题中的R代码和部分例题的数据文件等可从作者个人主页下载。  作者在编写本书的过程中参考了J.O.Berger教授的《统计决策论及贝叶斯分析》和茆诗松教授编写的《贝叶斯统计》等书中的一些内容,以及《贝叶斯分析》一书中由张伟平博士编写的有关贝叶斯统计计算的一些内容。在此表示衷心感谢。  本书编写准备过程中,中国科学技术大学统计与金融系的几个研究生帮助完成了本书部分中文的录入和排版,作者对他们的辛勤工作表示真诚的感谢。高等教育出版社为本书的出版给予了大力支持。在此一并致谢。

【Kafka从入门到成神系列 四】Kafka 消息丢失及 TCP 管理

大家好,我是爱敲代码的小黄,独角兽企业的Java开发工程师,Java领域新星创作者。这是我的系列专栏:Kafka 从入门到成神。如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步。如果感觉博主的文章还不错的话,请三连支持一下博主哦。

爱敲代码的小黄 1563

kafka无消息丢失配置

文章目录概念消息丢失的可能原因最佳实践 Kafka只对 “已提交” 的消息(committed message)做有限度的持久化保证; 概念 已提交消息: 当Kafka的若干个 Broker 成功的接收到一跳消息并写入到日志系统后,就会通知生产者程序这条消息已提交; 有限度的持久化保证:如果你的消息保存在 N 个 Broker 节点上,那么持久化的前提就是这 N 个Broker至少有一个节点...

leiax00 287

消息队列-kafka

本文将会对kafka进行介绍,首先介绍消息队列的一些基础知识,然后是kafka的基本概念和底层原理,以及kafka如何保证消息可靠性、消息不丢失,如何解决消息重复以及消息积压等问题,并且分析kafka为什么具有高吞吐量、低延迟等优势。最后,以golang语言来进行kafka的实战。

zhuohuashiyi 2220

Go语言实现Kafka消息队列

• RabbitMQ:基于内存的Erlang实现,适合中小规模业务。• Redis:数据主要在内存,重启可能丢失(需配置持久化)• Redis Streams:需要极低延迟的实时通知。• Kafka:消息持久化到磁盘,支持TB级数据存储。Go语言实现Kafka消息队列及与其他消息队列对比。• RabbitMQ:服务端推送(Push)一、Go语言快速实现Kafka消息队列。• 发送时指定分区键(如用户ID)二、Kafka与其他消息队列对比。(如:单集群可达百万TPS)(如:电商订单处理)

weixin_73833086的博客 670

Kafka如何保证消息不丢之无消息丢失配置

文章目录已提交与有限度生产者丢失数据异步发送消息解决方式消费者丢失数据最佳实践 已提交与有限度 Kafka对已提交的消息做有限度的持久化保证。 已提交消息:Kafka的若干个Broker成功接收到消息并写入日志文件后,告诉生产者已成功提交。已提交的定义如下 一个Broker成功保存消息为已提交 所有Broker都成功保存消息为已提交 有限度的持久化保证:有限度的意思是假如有N个Broker,要想保证持久化,就至少有一个存活。 生产者丢失数据 异步发送消息 当异步发送消息的时候,会立即返回,但是不能

凯凯王的技术生涯 611

为什么你的Go服务消息丢失?深度剖析消息队列整合中的9大陷阱

解决Go服务消息丢失难题,深入解析Go消息队列整合中的9大常见陷阱。涵盖生产消费确认、重试机制与异常处理等核心方案,提升系统可靠性。适用微服务与分布式场景,值得收藏。

BytePulse的博客 626

【八股消消乐】消息队列优化—消息丢失

🔍简历内容:熟悉Kafka写入语义、ISR、OSR、unclean选举基本原理。自主实现Kafka回查中间件并开源,利用分区表保证回查机制的高性能和高可用,基于哈希计算实现消息有序,最终实现消息回查机制,解决了xx业务消息丢失问题。 🚩面试问: - 在支持 Kafka 回查机制中,要是回查中间件把消息转发到业务 topic 了,但是标记成已发送失败,会发生什么? - 在支持 Kafka 回查机制中,你可以考虑把关系型数据库换成 Redis,这样换的话有什么优缺点?

文艺倾年的博客 1261
上一篇: Kafka(Go)教程(八)---生产者压缩算法详解及源码分析
下一篇: Kafka(Go)教程(十)---Kafka 是如何实现精确一次(exactly once)语义的?
探索云原生
博客等级 码龄9年 730粉丝 131原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值