大型互联网公司一般都会要求消息传递最大限度的不丢失,比如用户服务给代金券服务发送一个消息,如果消息丢失会造成用户未收到应得的代金券,最终用户会投诉。

为避免上面类似情况的发生,除了做好补偿措施,更应该在系设计的时候充分考虑各种异常,设计一个稳定、高可用的消息系统。

认识Kafka

看一下维基百科的定义

Kafka是分布式发布-订阅消息系统。它最初由LinkedIn公司开发,之后成为Apache项目的一部分。Kafka是一个分布式的,可划分的,冗余备份的持久性的日志服务。它主要用于处理活跃的流式数据。

kafka架构

Kafka的整体架构非常简单,是显式分布式架构,主要由producer、broker(kafka)和consumer组成。

Kafka架构(精简版)

Producer(生产者)可以将数据发布到所选择的topic(主题)中。生产者负责将记录分配到topic的哪一个 partition(分区)中。可以使用循环的方式来简单地实现负载均衡,也可以根据某些语义分区函数(如记录中的key)来完成。

Consumer(消费者)使用一个consumer group(消费组)名称来进行标识,发布到topic中的每条记录被分配给订阅消费组中的一个消费者实例。消费者实例可以分布在多个进程中或者多个机器上。

Kafka到底会不会丢失消息?

在讨论kafka是否丢消息前先来了解一下什么是 消息传递语义

消息传递语义

message delivery semantic 也就是消息传递语义,简单说就是消息传递过程中消息传递的保证性。主要分为三种:

  • at most once:最多一次。消息可能丢失也可能被处理,但最多只会被处理一次。
  • at least once:至少一次。消息不会丢失,但可能被处理多次。可能重复,不会丢失。
  • exactly once:精确传递一次。消息被处理且只会被处理一次。不丢失不重复就一次。

理想情况下肯定是希望系统的消息传递是严格exactly once,也就是保证不丢失、只会被处理一次,但是很难做到。

回到主角Kafka,Kafka有三次消息传递的过程:

  1. 生产者发消息给Kafka Broker。
  2. Kafka Broker 消息同步和持久化
  3. Kafka Broker 将消息传递给消费者。

在这三步中每一步都有可能会丢失消息,下面详细分析为什么会丢消息,如何最大限度避免丢失消息。

生产者丢失消息

先介绍一下生产者发送消息的一般流程(部分流程与具体配置项强相关,这里先忽略):

  1. 生产者是与leader直接交互,所以先从集群获取topic对应分区的leader元数据;
  2. 获取到leader分区元数据后直接将消息发给过去;
  3. Kafka Broker对应的leader分区收到消息后写入文件持久化;
  4. Follower拉取Leader消息与Leader的数据保持一致;
  5. Follower消息拉取完毕需要给Leader回复ACK确认消息;
  6. Kafka Leader和Follower分区同步完,Leader分区会给生产者回复ACK确认消息。

生产者发送数据流程

生产者采用push模式将数据发布到broker,每条消息追加到分区中,顺序写入磁盘。消息写入Leader后,Follower是主动与Leader进行同步。

Kafka消息发送有两种方式:同步(sync)和异步(async),默认是同步方式,可通过producer.type属性进行配置。

Kafka通过配置request.required.acks属性来确认消息的生产:

  • 0表示不进行消息接收是否成功的确认;不能保证消息是否发送成功,生成环境基本不会用。
  • 1表示当Leader接收成功时确认;只要Leader存活就可以保证不丢失,保证了吞吐量。
  • -1或者all表示Leader和Follower都接收成功时确认;可以最大限度保证消息不丢失,但是吞吐量低。

kafka producer 的参数acks 的默认值为1,所以默认的producer级别是at least once,并不能exactly once。

敲黑板了,这里可能会丢消息的!

  • 如果acks配置为0,发生网络抖动消息丢了,生产者不校验ACK自然就不知道丢了。
  • 如果acks配置为1保证leader不丢,但是如果leader挂了,恰好选了一个没有ACK的follower,那也丢了。
  • all:保证leader和follower不丢,但是如果网络拥塞,没有收到ACK,会有重复发的问题。

Kafka Broker丢失消息

Kafka Broker 接收到数据后会将数据进行持久化存储,你以为是下面这样的:

消息持久化,无cache

没想到是这样的:

消息持久化,有cache

操作系统本身有一层缓存,叫做 Page Cache,当往磁盘文件写入的时候,系统会先将数据流写入缓存中,至于什么时候将缓存的数据写入文件中是由操作系统自行决定。

Kafka提供了一个参数 producer.type 来控制是不是主动flush,如果Kafka写入到mmap之后就立即 flush 然后再返回 Producer 叫同步 (sync);写入mmap之后立即返回 Producer 不够用 flush 叫异步 (async)。

敲黑板了,这里可能会丢消息的!

Kafka通过多分区多副本机制中已经能最大限度保证数据不会丢失,如果数据已经写入系统 cache 中但是还没来得及刷入磁盘,此时突然机器宕机或者掉电那就丢了,当然这种情况很极端。

消费者丢失消息

消费者通过pull模式主动的去 kafka 集群拉取消息,与producer相同的是,消费者在拉取消息的时候也是找leader分区去拉取。

多个消费者可以组成一个消费者组(consumer group),每个消费者组都有一个组id。同一个消费组者的消费者可以消费同一topic下不同分区的数据,但是不会出现多个消费者消费同一分区的数据。

消费者群组消费消息

消费者消费的进度通过offset保存在kafka集群的__consumer_offsets这个topic中。

消费消息的时候主要分为两个阶段:

1、标识消息已被消费,commit offset坐标;

2、处理消息。

敲黑板了,这里可能会丢消息的!

场景一:先commit再处理消息。如果在处理消息的时候异常了,但是offset 已经提交了,这条消息对于该消费者来说就是丢失了,再也不会消费到了。

场景二:先处理消息再commit。如果在commit之前发生异常,下次还会消费到该消息,重复消费的问题可以通过业务保证消息幂等性来解决。

总结

那么问题来了,kafka到底会不会丢消息?答案是:会!

Kafka可能会在三个阶段丢失消息:

(1)生产者发送数据;

(2)Kafka Broker 存储数据;

(3)消费者消费数据;

在生产环境中严格做到exactly once其实是难的,同时也会牺牲效率和吞吐量,最佳实践是业务侧做好补偿机制,万一出现消息丢失可以兜底。

原文链接:https://mp.weixin.qq.com/s?__biz=MzIwODI1OTk1Nw==&mid=2650321970&idx=1&sn=3a26ed6f0323c945c1eacb05c758cd62

- END -

说两句:学习是一件时而郁郁寡欢时而开怀大笑的事情,越过瓶颈又是一片新天地,坚持坚持坚持。如果觉得本文对你有帮助,可以转发关注支持一下

kafka 重复消费和数据丢失_刨根问底,Kafka消息中间件到底会不会丢消息相关推荐

  1. 刨根问底,Kafka消息中间件到底会不会丢消息

    大型互联网公司一般都会要求消息传递最大限度的不丢失,比如用户服务给代金券服务发送一个消息,如果消息丢失会造成用户未收到应得的代金券,最终用户会投诉. 为避免上面类似情况的发生,除了做好补偿措施,更应该 ...

  2. kafka重复消费问题

    开篇提示:kafka重复消费的根本原因就是"数据消费了,但是offset没更新"!而我们要探究一般什么情况下会导致offset没更新? 今天查看Elasticsearch索引的时候 ...

  3. kafka 重复消费场景及解决方案

    1.与消费者有关的重要参数 在讨论重复消费之前,首先介绍一下kafka中几个跟消费有关的配置参数. enable.auto.commit 默认值true,表示消费者会周期性自动提交消费的offset ...

  4. 三张表有重复字段_什么?搞不定Kafka重复消费?

    点戳蓝字"架构之美"关注我们哦! 前言 今天我们聊一个话题,这个话题大家可能在面试过程中,或者是工作当中经常遇到 ?如何保证 Kafka 消息不重复消费?我们在做开发的时候为了程序 ...

  5. 什么?搞不定Kafka重复消费?

    来自:架构之美 前言 今天我们聊一个话题,这个话题大家可能在面试过程中,或者是工作当中经常遇到 ????如何保证 Kafka 消息不重复消费?我们在做开发的时候为了程序的健壮性,在使用 Kafka 的 ...

  6. kafka offset保存在哪里_《Kafka成神之路》- 索引类型

    在Kafka的数据路径下有很多.index和.timeindex后缀文件: .index文件,即Kafka中的位移索引文件 .timeindex文件,即时间戳索引文件. 1 OffsetIndex - ...

  7. RabbitMQ—重复消费、数据丢失和消息顺序性

    原文作者:weixin_49367803 原文地址:https://blog.csdn.net/weixin_49367803/article/details/108480256 一.如何保证消息不被 ...

  8. RabbitMQ如何解决被重复消费和数据丢失的问题?

    想想为什么要使用MQ? 1.解耦,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦! 2.异步,将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快 ...

  9. MQ问题集(kafka主从同步与高可用,MQ重复消费、幂等)

    1.kafka主从同步与高可用 https://1028826685.iteye.com/blog/2354570 http://developer.51cto.com/art/201808/5815 ...

最新文章

  1. 边做边思考,谷歌大脑提出并发RL算法,机械臂抓取速度提高一倍!
  2. SDWAN分支解决方案:sdwan能用于多分支的企业吗?
  3. Python学习笔记:面向对象高级编程(中上)
  4. 根据”so劫持”过360加固详细分析
  5. Java8 接口在变化
  6. python3安装教程配置配置阿里云
  7. 抛物型方程向前差分matlab,(整理)微分方程数值解(学生复习题).
  8. mongodb示例_MongoDB findAndModify()示例
  9. Yahoo Web UIs——Java开发者丰富的Web UI
  10. 微信小程序报错:Unhandled promise rejection TypeError: WebAssembly.instantiate(): Argument 0 must be a buffe
  11. 格式化字符串两种方式
  12. [XCTF-Reverse] 69 XCTF 3rd-RCTF-2017_MyDriver2-397
  13. Python中国象棋源代码及素材
  14. 百度推出新版团购导航 对团购导航造成冲击
  15. Interactive Speech and Noise Modeling for Speech Enhancement
  16. 从身边的移动支付说起
  17. HTTP超文本传输协议详解
  18. qt无法显示图片的原因
  19. 广告联盟EMU的理解
  20. java 虚拟机 Java内存结构 JVM垃圾回收机制算法

热门文章

  1. form 表单上传文件及传输数据的编码格式
  2. Flask入门之Virtualvenv的安装及使用(windows)
  3. 版本记录及相关数据汇总
  4. numpy 或者是 pandas 矩阵循环
  5. java后台访问接口
  6. 让jquery easyui datagrid列支持绑定嵌套对象
  7. [转]我倡导无政府主义编程—Fred George访谈录
  8. t-sql判断一个字符串是否为bigint的函数(全角数字需要判断为不合格)
  9. C/C++中判断两个变量是否相等,相减是否为0、大于0或小于0时要特别注意机器误差带来的影响
  10. 荣耀20搭载鸿蒙,荣耀20系列刚发布,搭载鸿蒙系统新机来袭,余承东已准备好!...