消息队列是面试中一定会被问到的技术模块,虽然它在面试题占比不及并发编程和数据库,但也属于面试中的关键性问题。所以今天我们就来看一道,MQ 中高频,但可能会打破你以往认知的一道面试题。

所谓的关键问题指的是这道面试题会影响你整体面试结果。

我们在面试消息队列(Message Queue,MQ)时,尤其是面试 Kafka 时,经常会被问到:如何保证消息不丢失?

那么,我们的回答会分为以下 3 部分:

  1. 保证生产者消息不丢失
  2. 保证 Kafka 服务(器端)消息不丢失
  3. 保证消费者消息不丢失

只有保证这 3 部分消息都不丢失,才能保证 Kafka 整体消息不丢失。

因为 Kafka 消息的传递流程如下(总共包含 3 部分):

1.如何保证生产者消息不丢失?

那怎么保证生产者消息不丢失呢?

要搞明白这个事,我们就要先了解一下生产者发送消息的执行流程。

Kafka 生产者发送消息的执行流程如下:



默认情况下,所有的消息会先缓存到 RecordAccumulator 缓存中,再由 Sender 线程拉取消息发送到 Kafka 服务器端,通过 RecordAccumulator 和 Sender 线程的协作,实现了消息的批量发送、性能优化和异常处理等功能,确保了消息的高效可靠传输。

1.1 RecordAccumulator 缓存作用

  1. 暂存消息:RecordAccumulator 是 Kafk a生产者中的一个关键组件,它充当了一个缓存的角色,用于暂存主线程(Main Thread)发送过来的消息。这些消息在 RecordAccumulato r中等待被 Sender 线程批量发送。
  2. 批量发送:RecordAccumulator 通过批量收集消息,减少了单个消息发送的网络请求次数,从而提高了发送效率。Sender 线程可以从 RecordAccumulator 中批量获取消息,一次性发送到 Kafka 集群,减少了网络传输的资源消耗。
  3. 性能优化:RecordAccumulator的缓存大小可以通过生产者客户端参数 buffer.memory 进行配置(默认值为 32MB)。合理的缓存大小设置可以平衡内存使用与发送效率,达到最优的性能表现。
  4. 内存管理:如果 RecordAccumulator 的缓存空间被占满,生产者再次调用 send() 方法发送消息时,会出现阻塞(默认阻塞时间为 60 秒,可通过 max.block.ms 参数配置)。如果阻塞超时,则会抛出异常。这种机制有助于防止生产者因为无限制地缓存消息而耗尽系统资源。
  5. ByteBuffer 复用:为了减少频繁创建和释放 ByteBuffer 所造成的资源消耗,RecordAccumulator 内部还维护了一个 BufferPool,用于实现 ByteBuffer 的复用。特定大小的 ByteBuffer 会被缓存起来,以便后续消息发送时重复使用。

1.2 Sender 线程作用

  1. 拉取消息:Sender 线程是 Kafka 生产者中的一个后台线程,它负责从 RecordAccumulator 中拉取缓存的消息。Sender 线程会定期轮询 RecordAccumulator,检查是否有新消息需要发送。
  2. 批量构建请求:当 Sender 线程发现有新消息需要发送时,它会构建一个或多个 ProducerRequest 请求。每个请求包含多个消息,以便进行有效的批量发送。这种批量发送机制可以显著提高网络传输效率。
  3. 发送消息到 Kafka 集群:Sender 线程将构建的 ProducerRequest 请求发送到 Kafka 集群的相应分区。它会根据分区的 Leader 节点信息,将消息发送给对应的 Broker 节点。
  4. 异常处理:在消息发送过程中,可能会出现网络故障、分区不可用等异常情况。Sender 线程负责处理这些异常,例如进行重试、重新连接等操作,以确保消息的可靠发送。
  5. 状态更新:一旦消息被成功接收并记录在 Kafka Broker 的日志中,Sender 线程会通知 RecordAccumulator 更新消息的状态。这样,生产者就能够知道哪些消息已经被成功发送,哪些消息还需要重试发送。

2.生产者消息丢失的两种场景

了解了 Kafka 生产者发送消息的流程之后,我们就能知道在这个环节丢失消息的情况有以下两种:

  1. 网络抖动(消息不可达):生产者与 Kafka 服务端之间的链路不可达,发送超时。此时各个节点的状态是正常,但消费端就是没有消费消息,就像消息丢失了一样。
  2. 无消息确认(ack):生产者消息发送之后,无 ack 消息确认,直接返回消息发送成功,但消息发送之后,Kafka 服务宕机或掉电了,导致消息丢失。

怎么解决这个问题呢?

2.1 网络波动问题处理

网络波动的话设置消息重试即可,因为网络抖动消息不可达,所以只要配置了重试次数,那么就会消息重试以此来保证消息不丢失。

在 Spring Boot 项目中,只需要在配置文件 application.yml 中,设置生产者的重试次数即可:

spring:
kafka:
producer:
retries: 3

2.2 消息确认设置

Kafka 生产者的 ACK(Acknowledgment)机制是指生产者在发送消息到 Kafka 集群后,等待确认的方式。这个机制决定了生产者何时认为消息已经成功发送,并直接影响到消息的可靠性和性能。

Kafka 生产者的 ACK 机制主要有以下三种类型。

① acks=0

生产者在将消息发送到网络缓冲区后,立即认为消息已被提交,不会等待任何来自服务器的响应。这时设置的重试次数 retries 无效。

特点

  • 最高性能:由于不需要等待任何确认,因此具有最高的吞吐量。
  • 最低可靠性:消息可能会在发送过程中丢失,生产者无法知道消息是否成功到达服务器。

适用场景:对消息可靠性要求不高,但追求极致性能的场景。

② acks=1

生产者在将消息发送到主题的分区 leader 后,等待 leader 的确认,即认为消息已被提交(此时 leader 写入成功,并没有刷新到磁盘),不用等待所有副本的确认。

特点

  • 中等可靠性和性能:提供了一定程度的可靠性,因为只有领导者副本确认消息后生产者才会收到确认。但如果领导者副本在确认后发生故障,而消息还未复制到其他副本,则消息可能会丢失。
  • 性能与可靠性平衡:在生产者性能和消息可靠性之间提供了一个折衷方案。

适用场景:适用于传输普通日志,允许偶尔丢失少量数据的场景。

③ acks=all 或 acks=-1

生产者需要等待所有同步副本(ISR, In-Sync Replicas)都成功写入消息后,才认为消息已被提交。

特点

  • 最高可靠性:只有当所有同步副本都确认接收到消息后,生产者才会收到确认,确保了消息的可靠性。
  • 较低性能:由于需要等待所有同步副本的确认,因此可能会导致消息发送的延迟增加,从而影响性能。

适用场景:适用于对消息可靠性要求极高的场景,如金融交易等关键任务应用。

在 Spring Boot 项目中,acks 可以在配置文件 application.yml 中设置:

spring:
kafka:
producer:
acks: all

3.acks=all消息一定不会丢失吗?

正常情况下当我们设置 acks=all 时,其实是可以保证数据不丢失了。但是有一种特殊情况,如果 Topic 只有一个 Partition(分区时),也就是只有一个 Leader 节点时,此时消息也是会丢失的

如果只有一个 Leader 节点,acks=all 的设置和 acks=1 的设置效果基本类似,当 Leader 确认消息之后,还没来得及将消息刷到磁盘之前宕机了,那么就会造成消息丢失。

万事必有妖,当面试官用疑问语句问你时,答案基本是否定的。如果是确定的话,面试官可能也就不会再问你了,所以当你听到一个有悖于常识的问题时,先努力思考这个问题还有没有其他答案。

课后思考

Kafka 服务器端和消费者如何保证消息不丢失呢?

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

被怼了:acks=all消息也会丢失?的更多相关文章

  1. kafka系列八、kafka消息重复和丢失的场景及解决方案分析

    消息重复和丢失是kafka中很常见的问题,主要发生在以下三个阶段: 生产者阶段 broke阶段 消费者阶段 一.生产者阶段重复场景 1.根本原因 生产发送的消息没有收到正确的broke响应,导致pro ...

  2. RocketMQ的消息是怎么丢失的

    前言 通过之前文章的阅读,有关RocketMQ的底层原理相信小伙伴们已经有了一个比较清晰的认识. 那么接下来王子想跟大家讨论一个话题,如果我们的项目中引入了MQ,势必要面对的一个问题,就是消息丢失问题 ...

  3. rabbitmq如何保证消息可靠性不丢失

    目录 生产者丢失消息 代码模拟 事务 confirm模式确实 数据退回监听 MQ事务相关软文推荐 MQ丢失信息 消费者丢失信息 之前我们简单介绍了rabbitmq的功能.他的作用就是方便我们的消息解耦 ...

  4. RabbitMQ 入门系列:6、保障消息:不丢失:发送方、Rabbit存储端、接收方。

    系列目录 RabbitMQ 入门系列:1.MQ的应用场景的选择与RabbitMQ安装. RabbitMQ 入门系列:2.基础含义:链接.通道.队列.交换机. RabbitMQ 入门系列:3.基础含义: ...

  5. 如何保证RabbitMQ的消息不会丢失?怎么保证RabbitMQ的可靠性?

    生产者: 原因: 由于网络原因导致消息发送失败,消息队列没有接收到生产者发送的消息,但生产者认为消息发送成功. 解决办法: transaction模式:事务模式:开启事务,发送消息,成功提交事务,失败 ...

  6. Kafka中的消息是否会丢失和重复消费(转)

    在之前的基础上,基本搞清楚了Kafka的机制及如何运用.这里思考一下:Kafka中的消息会不会丢失或重复消费呢?为什么呢? 要确定Kafka的消息是否丢失或重复,从两个方面分析入手:消息发送和消息消费 ...

  7. Kafka消息保证不丢失和重复消费问题

    使用同步模式的时候,有3种状态保证消息被安全生产,在配置为1(只保证写入leader成功)的话,如果刚好leader partition挂了,数据就会丢失.还有一种情况可能会丢失消息,就是使用异步模式 ...

  8. 一个自定义python分布式专用爬虫框架。支持断点爬取和确保消息100%不丢失,哪怕是在爬取进行中随意关停和随意对电脑断电。

    0.此框架只能用于爬虫,由框架来调度url请求,必须按照此方式开发,没有做到类似celery的通用分布式功能,也不方便测试.可以使用另外一个,基于函数式编程的,调度一切函数的分布式框架,做到了兼容任何 ...

  9. 121、商城业务---订单服务---rabbitmq消息积压、丢失、重复等解决方案

  10. 快速入门:弄懂Kafka的消息流转过程

    大家都知道 Kafka 是一个非常牛逼的消息队列框架,阿里的 RocketMQ 也是在 Kafka 的基础上进行改进的.对于初学者来说,一开始面对这么一个庞然大物会不知道怎么入手.那么这篇文章就带你先 ...

随机推荐

  1. 地铁查询app 结对作业三

    经过今天一下午的奋斗 安卓app 只剩下最难的部分了 最短路径问题 我们考虑用迪杰斯特拉算法 不过 没有做出来 还要继续去学习一下这个代码 并寻求网上代码的帮助

  2. 简约博客V1.1版本上线 + 一套新主题

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 简约博客V1.1版本上线 + 一套新主题 日期:2017- ...

  3. MATLAB神经网络工具箱使用介绍

      本文介绍MATLAB软件中神经网络拟合(Neural Net Fitting)工具箱的具体使用方法.   在MATLAB人工神经网络ANN代码这篇文章中,我们介绍了MATLAB软件中神经网络(AN ...

  4. Linux下挂载NTFS格式的U盘

    NTFS是Windows下的格式,在Linux下是识别不了的,要想在Linux上挂载NTFS格式的U盘需要安装软件以提供支持.软件名为ntfs-3g. 1.下载安装包 https://tuxera.c ...

  5. Jetpack Compose(7)——触摸反馈

    目录 一.点按手势 1.1 Modifier.clickable 1.2 Modifier.combinedClickable 二.滚动手势 2.1 滚动修饰符 Modifier.verticalSc ...

  6. 3562-IgH EtherCAT主站开发案例

  7. 【java深入学习第2章】Spring Boot 结合 Screw:高效生成数据库设计文档之道

    在开发过程中,数据库设计文档是非常重要的,它可以帮助开发者理解数据库结构,方便后续的维护和扩展.手动编写数据库设计文档不仅耗时,而且容易出错.幸运的是,可以使用Spring Boot和Screw来自动 ...

  8. 24 slide的pdf没有高亮开关

    安卓 app slide的pdf没有高亮开关

  9. Element-plus的徽章组件el-badge

    Element-plus的徽章组件el-badge Element Plus 是一个基于 Vue.js 的 UI 组件库,它提供了一系列的常用 UI 组件供开发者使用.其中,徽章组件(el-badge ...

  10. 毕业设计&毕业项目:基于springboot+jsp实现的健身房管理系统

    一.前言 在当今数字化时代,音乐已经成为人们生活中不可或缺的一部分.随着技术的飞速发展,构建一个用户友好.功能丰富的在线音乐平台成为了许多开发者和创业者的目标.本文将介绍如何使用SpringBoot作 ...