前言

今天分享一下kafka的消息丢失问题,kafka的消息丢失是一个很值得关注的问题,根据消息的重要性,消息丢失的严重性也会进行放大,如何从最大程度上保证消息不丢失,要从生产者,消费者,broker几个端来说。

消息发送和接收流程

kafka生产者生产好消息后,会将消息发送到broker节点,broker对数据进行存储,kafka的消息是顺序存储在磁盘上,以主题(topic),分区(partition)的逻辑进行划分,消息最终存储在日志文件中,消费者会循环从broker拉取消息。

那么从上图的图中可以看出kafka丢消息可能存在的三个地方分别为:

  • 生产者到broker
  • broker到磁盘
  • 消费者

生产者到broker消息丢失

生产者发送消息到broker是会存在消息丢失的,大多可能是由于网络原因引起的,消息中间件中一般都是通过ack来解决这个问题的,kafka中可以通过设置ack来解决这个问题。

acks有三种类型:

  • 0
  • 1
  • -1(all)

acks为0

acks设置为0,代表生产者发送消息后就不管不顾了,不用等待broker的任何响应,那么可能网络异常或者其他原因导致broker没有处理到到这条消息,那么消息就丢失了。

acks为1

acks设置为1,代表生产者发送消息到broker后,只需要broker的leader副本确认收到后就成功响应,不需要follower副本响应,就算follower副本崩溃了,也会成功响应。

acks为-1(all)

acks设置为-1,或者为all,那么生产者发送消息需要leader和follower都收到并写入消息才成功响应生产者,也就是ISR集合要全部写入,当ISR集合中只要有一个没有写入成功,那么就收到失败响应,所以acks=-1能够在最大程度上保证消息的不丢失,但是也是有条件的,需要ISR集合中有两个以上副本才能保证,如果只有一个副本,那么就是就只有一个leader,没有follower,如果leader挂掉,就不能选举出一个eader,消息自然也就丢失,这和acks=1是一样的

解决消息丢失

从上面三种类型的acks中我们可以看出,acks=-1是保证消息从生产者到broker不丢失的最佳设置方式,不过我们也能想到,它需要ISR每个副本都成功应答,所以它的效率自然没有前面两个高,不过此篇我们讨论的是保证消息不丢失问题,所以一切从不丢失层面区说。

如果消息发送失败,那么生产者可以重试发送消息,可以手动在代码中编写消息重发逻辑,也可以配置重试参数。

  • retries
  • retry.backoff.ms

retries表示重试次数,retry.backoff.ms表示重试时间间隔,比如第一次重试依旧没成功,那么隔多久再进行重试,kafka重试的底层逻辑是将没发送成功的消息重新入队,因为kafka的生产者生产消息后,消息并非就直接发送到broker,而是保存在生产者端的收集器(RecordAccumulator),然后由Sender线程去获取RecordAccumulator中的消息,然后再发送给broker,当消息发送失败后,会将消息重新放入RecordAccumulator中,具体逻辑可以看kafka的生产者端Sender的源码。

消息重发引起的消息顺序性问题

要注意,消息发送失败进行重发不能保证消息发送的顺序性,这里的顺序性是单分区顺序性,如果服务对于消息的顺序性有严格的要求,那么我们可以通过设置属性max.in.flight.requests.per.connection=1来保证消息的顺序性,这个配置对应的是kafka中InFlightRequestsmax.in.flight.requests.per.connection代表请求的个数,kafka在创建Sender的时候会判断,如果maxInflightRequests为1,那么guaranteeMessageOrder就为true,就能保证消息的顺序性。

broker到磁盘丢消息

broker收到消息后,需要将消息写入磁盘的log文件中,但是并不是马上写,因为我们知道,生产者发送消息后,消费者那边需要马上获取,如果broker要写入磁盘,那么消费者拉取消息,broker还要从log文件中获取消息,这显然是不合理的,所以kafka引入了(page cache)页缓存。

page cache是磁盘和broker之间的消息映射关系,它是基于内存的,当broker收到消息后,会将消息写入page cache,然后由操作系统进行刷盘,将page cache中的数据写入磁盘。

如果broker发生故障,那么此时page cache的数据就会丢失,broker端可以设置刷盘的参数,比如多久刷盘一次,不过这个参数不建议去修改,最好的方案还是设置多副本,一个分区设置几个副本,当broker故障的时候,如果还有其他副本,那么数据就不会丢失。

消费者丢消息

kafka的消费模式是拉模式,需要不断地向broker拉取消息,拉取的消息消费了以后需要提交offset,也就是提交offset这里可能会出现丢消息,kafka中提供了和offset相关的几个配置项。

  • enable.auto.commit
  • auto.commit.interval.ms
  • auto.offset.reset

下面我们先了解一下kafka offset的提交和参数详解。

enable.auto.commit代表是否自动提交offset,默认为true,auto.commit.interval.ms代表多久提交一次offset,默认为5秒。

如下图,当前消费者消费到了分区中为3的消息。

那么下次当消费者读取消息的时候是从哪里读取呢,当然从4开始读取,因为是从上次读取的offset的下一位开始读取,所以我们就说当前消费组的offset为4,,因为下次是从4开始消费,如果5秒之内又消费了两条消息然后自动提交了offset,那么此时的offset如下:

enable.auto.commit如果为false,就代表不会自动提交offset。

auto.offset.reset=latest代表从分区中最新的offset处开始读取消息,比如某个消费者组上次提交的偏移量为5,然后后面又生产了2条消息,再次读取消息时,读取到的是6,7,8这个三个消息,如果enable.auto.commit设置为false,那么不管往分区中写入多少消息,都是从6开始读取消息。

此时如果一个新的的消费组订阅了这个分区,因为这个消费者组没有在这个分区提交过offset,所以它获取消息并不是从6开始获取,而是从1开始获取。

所以可知每个消费者组在分区中的offset是独立的。

auto.offset.reset还可以设置为earliestnone,使用earliest,如果此消费组从来没有提交过offset,那么就从头开始消费,如果提交过offset,那么就从最新的offset处消费,就和latest一样了,使用none,如果消费组没有提交过offset,在分区中找不到任何offset,那么就会抛出异常。

org.apache.kafka.clients.consumer.NoOffsetForPartitionException: Undefined offset with no reset policy for partitions: [stock1-0]

上面我们初步了解了offset的一些知识,对offset的提交和和读取有一些了解,因为上面我们只提及offset的自动提交,而自动提交的主动权在kafka,而不在我们,所以可能因为一些原因而导致消息丢失。

消息处理异常

当我们收到消息后对消息进行处理,如果在处理的过程中发生异常,而又设置为自动提交offset,那么消息没有处理成功,offset已经提交了,当下次获取消息的时候,由于已经提交过ofset,所以之前的消息就获取不到了,所以应该改为手动提交offset,当消息处理成功后,再进行手动提交offset。

总结

关于kafka的消息丢失问题和解决方案就说到这里,我们分别从生产者到broker,broker到磁盘以及消费者端进行说明,也引申出一些知识点,可能平时没有遇到消息丢失的情况,那是因为网络比较可靠,数据量可能不大,但是如果要真的实现高可用,高可靠,那么就需要对其进行设计。

今天的分享就到这里,感谢你的观看,我们下期见,如果文中有说得不合理或者不正确的地方,希望你能进行指点

 
 

一文了解清楚kafka消息丢失问题和解决方案的更多相关文章

  1. 转载来自朱小厮博客的 一文看懂Kafka消息格式的演变

    转载来自朱小厮博客的 一文看懂Kafka消息格式的演变     ✎摘要 对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在 ...

  2. Kafka消息丢失

    1.Kafka消息丢失的情况: (1)auto.commit.enable=true,消费端自动提交offersets设置为true,当消费者拉到消息之后,还没有处理完 commit interval ...

  3. 实际业务处理 Kafka 消息丢失、重复消费和顺序消费的问题

    关于 Kafka 消息丢失.重复消费和顺序消费的问题 消息丢失,消息重复消费,消息顺序消费等问题是我们使用 MQ 时不得不考虑的一个问题,下面我结合实际的业务来和你分享一下解决方案. 消息丢失问题 比 ...

  4. 一文看懂Kafka消息格式的演变

    摘要 对于一个成熟的消息中间件而言,消息格式不仅关系到功能维度的扩展,还牵涉到性能维度的优化.随着Kafka的迅猛发展,其消息格式也在不断的升级改进,从0.8.x版本开始到现在的1.1.x版本,Kaf ...

  5. 【消息队列面试】11-14:kafka高可靠、高吞吐量、消息丢失、消费模式

    十一.kafka消息高可靠的解决方案 1.高可靠=避免消息丢失 解决消息丢失的问题 2.如何解决 (1)保证消息发送是可靠的(发成功了/落到partition) a.ack参数 发送端,采用ack机制 ...

  6. 如何处理RabbitMQ 消息堆积和消息丢失问题

    消息堆积 解决方案: 增加消费者或后台相关组件的吞吐能力 增加消费的多线程处理 根据不同的业务实现不同的丢弃任务,选择不同的策略淘汰任务 默认情况下,RabbitMQ消费者为单线程串行消费,设置并行消 ...

  7. Kafka无消息丢失配置

    Kafka到底会不会丢数据(data loss)? 通常不会,但有些情况下的确有可能会发生.下面的参数配置及Best practice列表可以较好地保证数据的持久性(当然是trade-off,牺牲了吞 ...

  8. kafka消息会不会丢失

    转载:https://baijiahao.baidu.com/s?id=1583469327946027281&wfr=spider&for=pc 消息发送方式 想清楚Kafka发送的 ...

  9. Kafka leader副本选举与消息丢失场景讨论

    如果某个broker挂了,leader副本在该broker上的分区就要重新进行leader选举.来简要描述下leader选举的过程 1.4.1 KafkaController会监听ZooKeeper的 ...

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

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

随机推荐

  1. shell语法1-概论、注释、变量、字符串

    如果感觉有点忘了或者有点懵,敲出来测试测试就好了 一:概论 Linux系统中一般默认使用bash,文件开头需要写#! /bin/bash,指明bash为脚本解释器chmod +x filename:使 ...

  2. el-dropdown-item 添加点击 事件无效 (vue)

    如图 无效!!! 为什么呢?? 想了一下,可能是因为 el-dropdown-item   没有自定义click事件 so! 解决办法就是  添加原生事件  :  @click.native   还有 ...

  3. 解决通过Eclipse启动Tomcat-Run On Server出现The selection cannot be run on any server

    有时候通过Eclipse启动Tomcat-Run On Server会出现The selection cannot be run on any server的情况如下图: 这是因为没有在eclipse ...

  4. WEB攻击与防御技术 pikachu——文件包含下载上传漏洞

    文件包含漏洞 一.LOCAL 上来就是一个选择,当我们选择一个球员的时候,如图所示,url会提交一个get请求 如果这个服务器架设在linux上我们就可以一直../../../../../到根目录然后 ...

  5. flume往kafka中导入数据

    1.编辑flume的配置文件 a1.sources = r1 a1.channels = c1 # Describe/configure the source a1.sources.r1.type = ...

  6. kafka工具的使用-发送数据

    1.了解推送数据的是哪个topic,选择对应topic下面的partition分区 2.右侧界面选择Data,并点击『+』号: 3.可选择添加单个消息『add Single Message』或者添加多 ...

  7. Java基础Day7-值传递和引用传递

    一.值传递 Java都是值传递. 值传递:是指在调用函数时,将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,就不会影响到实际参数. 值传递是对基本数据类型而言. 二.引用传递 引用传递 ...

  8. 库已安装但找不到ttkbootstrap库

    cmd里装,弹提示Requirement already satisfied pip install --target=F:\Python37\lib ttkbootstrap https://blo ...

  9. 我的JAVA后端技术选型(2020版)

    JAVA后端技术选型(2020版)集群网关: LVS+keepalived 或 HAProxy服务网关 : zuul1.x注册中心: Eureka,Zookeeper配置中心: Spring Clou ...

  10. 探秘ThreadLocal

    一 类结构 主要是set(T), get(), remove()方法 二  TheadLocal是什么时候创建的 threadLocal的初始化, lazy creating, 用到的时候(get 或 ...