kafka如何保证不丢消息

ps:这篇文章自我感觉说的很大白话了!希望你们看过了之后能有收获。

不了解 Kafka 的朋友建议先看一看我的下面这几篇文章,第一篇一定要看,其他的可以按需学习。

  1. 入门篇!大白话带你认识 Kafka!
  2. 5分钟带你体验一把 Kafka
  3. Kafka系列第三篇!10 分钟学会如何在 Spring Boot 程序中使用 Kafka 作为消息队列?

生产者丢失消息的情况

生产者(Producer) 调用send方法发送消息之后,消息可能因为网络问题并没有发送过去。

所以,我们不能默认在调用send方法发送消息之后消息消息发送成功了。为了确定消息是发送成功,我们要判断消息发送的结果。但是要注意的是 Kafka 生产者(Producer) 使用 send 方法发送消息实际上是异步的操作,我们可以通过 get()方法获取调用结果,但是这样也让它变为了同步操作,示例代码如下:

详细代码见我的这篇文章:Kafka系列第三篇!10 分钟学会如何在 Spring Boot 程序中使用 Kafka 作为消息队列?

SendResult<String, Object> sendResult = kafkaTemplate.send(topic, o).get();
if (sendResult.getRecordMetadata() != null) {logger.info("生产者成功发送消息到" + sendResult.getProducerRecord().topic() + "-> " + sendResult.getProducerRecord().value().toString());
}

但是一般不推荐这么做!可以采用为其添加回调函数的形式,示例代码如下:

        ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(topic, o);future.addCallback(result -> logger.info("生产者成功发送消息到topic:{} partition:{}的消息", result.getRecordMetadata().topic(), result.getRecordMetadata().partition()),ex -> logger.error("生产者发送消失败,原因:{}", ex.getMessage()));

如果消息发送失败的话,我们检查失败的原因之后重新发送即可!

另外这里推荐为 Producer 的retries(重试次数)设置一个比较合理的值,一般是 3 ,但是为了保证消息不丢失的话一般会设置比较大一点。设置完成之后,当出现网络问题之后能够自动重试消息发送,避免消息丢失。另外,建议还要设置重试间隔,因为间隔太小的话重试的效果就不明显了,网络波动一次你3次一下子就重试完了

消费者丢失消息的情况

我们知道消息在被追加到 Partition(分区)的时候都会分配一个特定的偏移量(offset)。偏移量(offset)表示 Consumer 当前消费到的 Partition(分区)的所在的位置。Kafka 通过偏移量(offset)可以保证消息在分区内的顺序性。

当消费者拉取到了分区的某个消息之后,消费者会自动提交了 offset。自动提交的话会有一个问题,试想一下,当消费者刚拿到这个消息准备进行真正消费的时候,突然挂掉了,消息实际上并没有被消费,但是 offset 却被自动提交了。

解决办法也比较粗暴,我们手动关闭闭自动提交 offset,每次在真正消费完消息之后之后再自己手动提交 offset 。 但是,细心的朋友一定会发现,这样会带来消息被重新消费的问题。比如你刚刚消费完消息之后,还没提交 offset,结果自己挂掉了,那么这个消息理论上就会被消费两次。

Kafka 弄丢了消息

我们知道 Kafka 为分区(Partition)引入了多副本(Replica)机制。分区(Partition)中的多个副本之间会有一个叫做 leader 的家伙,其他副本称为 follower。我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。生产者和消费者只与 leader 副本交互。你可以理解为其他副本只是 leader 副本的拷贝,它们的存在只是为了保证消息存储的安全性。

试想一种情况:假如 leader 副本所在的 broker 突然挂掉,那么就要从 follower 副本重新选出一个 leader ,但是 leader 的数据还有一些没有被 follower 副本的同步的话,就会造成消息丢失。

设置 acks = all

解决办法就是我们设置 acks = all。acks 是 Kafka 生产者(Producer) 很重要的一个参数。

acks 的默认值即为1,代表我们的消息被leader副本接收之后就算被成功发送。当我们配置 acks = all 代表则所有副本都要接收到该消息之后该消息才算真正成功被发送。

设置 replication.factor >= 3

为了保证 leader 副本能有 follower 副本能同步消息,我们一般会为 topic 设置 replication.factor >= 3。这样就可以保证每个 分区(partition) 至少有 3 个副本。虽然造成了数据冗余,但是带来了数据的安全性。

设置 min.insync.replicas > 1

一般情况下我们还需要设置 min.insync.replicas> 1 ,这样配置代表消息至少要被写入到 2 个副本才算是被成功发送。min.insync.replicas 的默认值为 1 ,在实际生产中应尽量避免默认值 1。

但是,为了保证整个 Kafka 服务的高可用性,你需要确保 replication.factor > min.insync.replicas 。为什么呢?设想一下加入两者相等的话,只要是有一个副本挂掉,整个分区就无法正常工作了。这明显违反高可用性!一般推荐设置成 replication.factor = min.insync.replicas + 1

设置 unclean.leader.election.enable = false

Kafka 0.11.0.0版本开始 unclean.leader.election.enable 参数的默认值由原来的true 改为false

我们最开始也说了我们发送的消息会被发送到 leader 副本,然后 follower 副本才能从 leader 副本中拉取消息进行同步。多个 follower 副本之间的消息同步情况不一样,当我们配置了 unclean.leader.election.enable = false 的话,当 leader 副本发生故障时就不会从 follower 副本中和 leader 同步程度达不到要求的副本中选择出 leader ,这样降低了消息丢失的可能性。

Reference

  • Kafka 官方文档: https://kafka.apache.org/documentation/
  • 极客时间—《Kafka核心技术与实战》第11节:无消息丢失配置怎么实现?

推荐阅读

《70k Star Java开源项目出PDF阅读版本啦!》 。

作者介绍: Github 70k Star 项目 JavaGuide(公众号同名) 作者。每周都会在公众号更新一些自己原创干货。公众号后台回复“1”领取Java工程师必备学习资料+面试突击pdf。

面试官问我如何保证Kafka不丢失消息?我哭了!相关推荐

  1. 面试官再问我如何保证 RocketMQ 不丢失消息,这回我笑了!

    0x00. 消息的发送流程 一条消息从生产到被消费,将会经历三个阶段: 生产阶段,Producer 新建消息,然后通过网络将消息投递给 MQ Broker 存储阶段,消息将会存储在 Broker 端磁 ...

  2. 面试官问: 如何保证 MQ消息是有序的?

    为了系统间解耦,我们通常会引入MQ框架,大家各司其职共同完成上下游的业务流程. 大致过程: 生产端,创建一条消息,通过网络发送到MQ Server MQ将 消息存储在topic 的一个分区里 消费端, ...

  3. 面试官问:Kafka 会不会丢消息?怎么处理的?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! Kafka存在丢消息的问题,消息丢失会发生在Broker, ...

  4. 【283期】面试官问:高并发场景下,如何保证全局唯一分布式 ID 生成?

    点击上方"Java精选",选择"设为星标" 别问别人为什么,多问自己凭什么! 下方有惊喜,留言必回,有问必答! 每一天进步一点点,是成功的开始... 前言 系统 ...

  5. 【059期】面试官问:序列化是什么,为什么要序列化,如何实现?

    >>号外:关注"Java精选"公众号,回复"面试资料",免费领取资料!"Java精选面试题"小程序,3000+ 道面试题在线刷, ...

  6. 关于使用消息队列今天被面试官问倒了

    为什么使用消息队列 其实就是问问你消息队列都有哪些使用场景,然后你项目里具体是什么场景,说说你在这个场景里用消息队列是什么? 面试官问你这个问题,期望的一个回答是说,你们公司有个什么业务场景,这个业务 ...

  7. 大叔手记(10):别再让面试官问你单例

    大叔手记(10):别再让面试官问你单例(暨6种实现方式让你堵住面试官的嘴) ... 2012-2-19 09:03| 发布者: benben| 查看: 283| 评论: 0 摘要: 引子经常从Recr ...

  8. eureka自我保护时间_阿里面试官问我:到底知不知道什么是Eureka,这次,我没沉默...

    文章首发:阿里面试官问我:到底知不知道什么是Eureka,这次,我没沉默 什么是服务注册? 首先我们来了解下,服务注册.服务发现和服务注册中心的之间的关系. 举个形象的例子,三者之间的关系就好像是供货 ...

  9. 面试官问:如果MySQL引起CPU消耗过大,你会怎么优化

    转载自  面试官问:如果MySQL引起CPU消耗过大,你会怎么优化 谁在消耗cpu? 用户+系统+IO等待+软硬中断+空闲 祸首是谁? 用户 用户空间CPU消耗,各种逻辑运算 正在进行大量tps 函数 ...

最新文章

  1. Overview of ISA and TMG Networking and ISA Networking Case Study (Part 1)
  2. mysqldump备份数据库
  3. 如何使用Windows开发机为iPhone开发?
  4. [Issue Fixed]-执行脚本时出现invalid option错误
  5. 【直播预告】第四范式Intel AI应用与异构内存编程挑战赛专场活动开启报名
  6. Linux 格式化输出当前系统时间
  7. 生态和场景一站式集成?来看看小程序的“共享主义”
  8. lisp实战文库_LISP编程举例
  9. git拉取分支报错:fatal:‘XXX' is not a commit and a branch ‘XXX' cannot be created from
  10. java 快死了_如果Java快死了,那么它肯定看起来非常健康
  11. Python RSA加密与解密 公钥和私钥 读写pem文件
  12. Oracle中 char varchar varchar2的区别
  13. ftk学习记(输入法篇)
  14. IdentityServer4 And AspNetCore.Identity Get AccessToken 问题
  15. Android开发4: Notification编程基础、Broadcast的使用及其静态注册、动态注册方式...
  16. 【数学建模】基于matlab重庆三号线地铁运行仿真【含Matlab源码 042期】
  17. 虚拟空间 搬迁 云服务器,服务器空间搬迁到虚拟主机
  18. vtp服务器作用,VTP
  19. DataNode生命线消息
  20. 【复杂网络系列】模块度(Modularity )的计算方法

热门文章

  1. 学Python怎么月入过万,迎娶白富美,走上人生巅峰?
  2. SSB介绍(pbch和dmrs需要补充)
  3. LaTeX公式自动换行
  4. WEB渗透测试知识梳理-注入类-1-SQL注入-Mysql
  5. tinymce 去掉编辑器换行默认增加的p标签
  6. 【推荐收藏】【机器学习实战】训练模型(挑战全网最全)
  7. 开源ITSM工具iTop从入门到实施
  8. NPDP 和PMP 产品经理应该考哪个?
  9. 作为产品经理,有必要考各种证书吗?比如:pmp,npdp。证书对薪资有影响吗?
  10. android菊花动画,Android仿ios加载时菊花图