Kafka从入门到放弃(三) —— 详说生产者
上一篇对Kafka做了简单介绍,还没看的朋友可以点击下方链接。
消息中间件必须与生产者和消费者一起存在才有意义,这次先来聊聊Kafka的生产者。
在开始之前,先了解一下消息在Kafka中是如何存储的,如下图所示,一般我们称那些数字为offset(偏移量)一般来说,消息在持久化后应该是有序的,这里的有序是针对分区的,而不是针对 Topic 的。
而且,生产者写入消息时,是往 Leader 写入,Follower 从 Leader 进行复制。

别看生产者只是发消息,调用 API 也是几行代码,但它的学问多着呢。为更好地理解后面的内容,请带着以下问题阅读:
- 生产者发送消息前会做什么准备?
- 生产者发送消息怎么保证数据不丢失?
- 生产者发送消息如何保证消息有序性?
- 生产者发送的消息是怎么分区的?
生产者设计了一个缓冲池,可以通过修改 buffer.memory 参数设置其大小;缓冲池内又有多个 Batch,当有多个消息需要写入同一个分区时,消息会先往 Batch 里面写入,等消息达到 batch.size 的时候开始发送,如果 batch.size 设置太小,生产者会频繁发送消息,带来更多的网络开销;
有些读者可能有这个疑问,如果有时候生产者生产的消息很少很小,一直达不到批次的大小,而消费者对时效性要求比较高,这种情况怎么办?其实,默认情况下,只要有线程,即使批次里只有一条消息,也会直接发送出去。但是,可以设置参数 linger.ms 来指定等待消息加入批次的时间,只要当批次消息达到 batch.size 或者等待时间达到 linger.ms 的时候,消息就会发送。
除此之外,生产者可以对消息进行压缩,以降低网络开销以及存储开销,通过设置参数 compression.type 设置相应的压缩算法。
先抛开 Kafka 现有确认机制,假如一条消息发到对应分区后,没有任何确认就紧接着发送第二条,很难不造成数据丢失。
于是我们让分区在收到消息后返回确认消息给生产者,生产者收到后发送下一条。
就这样,消息很顺利地发着,正好在 Leader 拿到最新的消息并返回确认给生产者的时候,Leader 挂了,此时,Follower 还没同步最新的消息,而生产者已经接收到了分区返回的确认,这时候还是丢了数据。
因此我们让 Leader 以及参与复制的 Follower 都收到消息后返回确认,这样就能最大程度保证消息不丢失,不过延迟较高。
针对上述的情况,Kafka 设置了一个 acks 参数,指定了必须有几个副本收到消息生产者才认为是写入成功了。
- acks=0,生产者只管写入,不会等待 Broker 返回响应,默认成功。这种情况最容易造成数据丢失,不过吞吐量最高;
- acks=1,Leader 收到消息后响应,生产者才认为写成功,这种也会造成丢失;
- acks=all,Kafka 集群内部会维护一个副本清单 ISR(后续会写,再此不做描述),当 ISR 里的所有副本都收到消息,才认为写入成功,最大程度保证消息不丢失,不过可能会造成延迟较高。
另外,Kafka 还有一个参数 retries,表示当消息发送失败后,生产者重试的次数,默认为0,如果对丢失消息零容忍,那就不能设置为0.
事实上,生产者在收到分区返回的确认消息前,还是可以持续发送消息的,这个可以通过设置 max.in.flight.requests.per.connection 参数进行修改,这个参数指定了生产者在收到响应前可以发送多少个消息。
这里需要注意的是,如果这个参数不为1,而 retries 参数也不为 0 的时候,当发生重试的时候,有可能造成分区数据顺序错乱。在有些场景下,顺序是很重要的,比如分析交易流水的过程,某个第一次存款的客户先存1块钱再取1块钱是正常的,但反过来可能就有点奇怪了。
所以,如果要保证数据不丢失,同时要保证数据有序性,就需要将 retries 设置为非 0 整数,max.in.flight.requests.per.connection 设置为 1,注意不是 0.
生产者可以指定键作为分区键,如果不指定,生产者会使用轮询算法将消息均匀的发到各个分区上

但如果指定了分区键,Kafka 会使用自己的 hash 算法获得 hash 值,然后根据 hash 值发到相应的分区。
到这,回顾一下前面的几个问题,是不是有点豁然开朗了?
如果觉得写得不错,对你有帮助,麻烦点个小小的赞,谢谢!
转载请注明出处:工众号“大数据的奇妙冒险”,博客园 Lyu_zt
Kafka从入门到放弃(三) —— 详说生产者的更多相关文章
- Kafka从入门到放弃(三)—— 详说消费者
之前介绍了Kafka以及生产者,包括它的一些特性和参数,这回写一下消费者. 之前没看得可以点击链接阅读. Kafka从入门到放弃(一) -- 初识Kafka Kafka从入门到放弃(二) -- 详说生 ...
- kafka原理和实践(三)spring-kafka生产者源码
系列目录 kafka原理和实践(一)原理:10分钟入门 kafka原理和实践(二)spring-kafka简单实践 kafka原理和实践(三)spring-kafka生产者源码 kafka原理和实践( ...
- hive从入门到放弃(三)——DML数据操作
上一篇给大家介绍了 hive 的 DDL 数据定义语言,这篇来介绍一下 DML 数据操作语言. 没看过的可以点击跳转阅读: hive从入门到放弃(一)--初识hive hive从入门到放弃(二)--D ...
- storm从入门到放弃(三),放弃使用《StreamId》特性。
序:StreamId是storm中实现DAG有向无环图的重要一个特性,但是从实际生产环境来看,这个功能其实蛮影响生产环境的稳定性的,我们系统在迭代时会带来整体服务的不可用. StreamId是stor ...
- storm从入门到放弃(三),放弃使用 StreamId 特性
序:StreamId是storm中实现DAG有向无环图的重要一个特性,但是从实际生产环境来看,这个功能其实蛮影响生产环境的稳定性的,我们系统在迭代时会带来整体服务的不可用. StreamId是stor ...
- Kafka从入门到放弃(一) —— 初识Kafka
消息中间件的使用已经越来越广泛,基本上具有一定规模的系统都会用到它,在大数据领域也是个必需品,但为什么使用它呢?一个技术的广泛使用必然有它的道理. 背景与问题 以前一些传统的系统,基本上都是" ...
- robotium从入门到放弃 三 基于apk的自动化测试
1.apk重签名 在做基于APK的自动化测试的过程中,需要确保的一点是,被测试的APK必须跟测试项目具有相同的签名,那怎么做才能确保两者拥有相同的签名呢?下面将给出具体的实现方法. 首先将被测 ...
- Go语言从入门到放弃(三) 布尔/数字/格式化输出
本章主要介绍Go语言的数据类型 布尔(bool) 布尔指对或者错,也就是说bool只有两个值, True 或 False 两个类型相同的值可以使用比较运算符来得出一个布尔值 当两个值是完全相同的情况下 ...
- MyBatis从入门到放弃三:一对一关联查询
前言 简单来说在mybatis.xml中实现关联查询实在是有些麻烦,正是因为起框架本质是实现orm的半自动化. 那么mybatis实现一对一的关联查询则是使用association属性和resultM ...
随机推荐
- [cf1326F]Wise Men
对答案序列求一个高维后缀和,再通过差分将其解出,后者复杂度为$o(n2^{n})$ 对于求后缀和后的结果,即01序列仅要求1处有边(不要求0处没有边),那么也即要求将原图划分为若干条长度给定且没有公共 ...
- [hdu6973]Bookshop
将询问拆成$x$到$lca$和$lca$($lca$靠近$y$的儿子)到$y$两部分,分别处理(后者以前者的答案为基础) 两者是类似地,不妨仅考虑前者:用树剖将该询问拆成dfs序上若干个 ...
- [atAGC051D]C4
考虑将两次移动作为一个整体,两次移动的效果分为:$s-u$.$u-s$和原地不动 对于从$s$回到$s$路径,必然有前两种效果使用次数相同,假设都为$i$(枚举),那么原地不动的次数$j=\frac{ ...
- CG Kit探索移动端高性能渲染
内容来源:华为开发者大会2021 HMS Core 6 Graphics技术论坛,主题演讲<CG Kit探索移动端高性能渲染> 演讲嘉宾:华为海思麒麟GPU团队工程师 大家好,我来自华为海 ...
- 【 [SCOI2016]幸运数字】
P3292 [SCOI2016]幸运数字 想法 倍增加上线性基就行惹 线性基的合并可以通过把一个线性基的元素插入到另一个里实现 #include<iostream> #include< ...
- 洛谷 P6570 - [NOI Online #3 提高组] 优秀子序列(集合幂级数+多项式)
洛谷题面传送门 首先 \(3^n\) 的做法就不多说了,相信对于会状压 dp+会枚举子集的同学来说不算困难(暴论),因此这篇博客将着重讲解 \(2^nn^2\) 的做法. 首先如果我们把每个 \(a_ ...
- 【豆科基因组】鹰嘴豆Chickpea (Cicer arietinum L.)429个自然群体重测序2019NG
目录 一.来源 二.结果 材料测序.变异检测.群体结构和LD衰减 驯化后经历选择的候选基因组区域 起源中心.迁移路线和多样性 GWAS 一.来源 Resequencing of 429 chickpe ...
- [R] ignore.case区分大小写参数
字符串操作的函数(如contains),很多都包含ignore.case参数,默认是T,即不分大小写,稍不注意就会掉坑里,最好的习惯是下意识地加入这个参数. 举个例子: 我要选择An的列,就用下面这个 ...
- miRNA预测工具miRDeep-P2
之前讲过预测植物miRNA的一款软件miR-PREFER, 今天在介绍一款软件miRDeep-p2, 也叫miRDP2 安装 在此之前,应安装一下软件 Bowite, Bowtie2, Vienna ...
- wireshatk_teach
wireshark抓包新手使用教程 Wireshark是非常流行的网络封包分析软件,可以截取各种网络数据包,并显示数据包详细信息.常用于开发测试过程各种问题定位.本文主要内容包括: 1.Wiresha ...