Kafka生产者

本文深入解析Kafka的参数设置,包括序列化、客户端ID、重试机制、ACK确认及消息大小等,探讨其对消息可靠性和性能的影响。同时,阐述了Kafka如何保证消息顺序性,以及在配置上确保消息完全有序的关键。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、 重要参数

1.1 serializer

为什么需要这serializer? 因为broker 端接收的消息必须以字节数组(byte [] )的形式存在。
常见值:

  • org apache kafka.common.serialization.StringSerializer

1.2 client.id

这个参数都说建议显示指定,但也都没说为什么么

这个参数用来设定 KafkaProducer 应的客户端 id 默认值为“” 如果客户端不设置, KafkaProducer自动生成一个非空字符串,内容形式如“producer-I ”“producer -2 ,即字符串“producer-"与数字的拼接。

1.3 retries

KafkaProducer 一般会发生两种类型的异常 可重试的异常和不可重试的异常 。常见的可重试异常有

  • NetworkException
  • LeaderNotAvailableException
  • UnknownTopicOrPartitionException
  • NotEnoughReplicasException
  • NotCoordinatorException

比如 NetworkException 表示网络异常,这个有可能是由于网络瞬时故障而导致的异常,可以通过重试解决;又比如
LeaderNotAvailableException 表示分区的 leader 副本不可用,这个异常通常发生在 leader 副本下线而新的 eader 副本选举完成之前,重试之后可以重新恢复。
不可重试的异常:RecordTooLargeException,这种异常直接抛出异常,不会重试。
当然必须配置重试次数,默认是0,即使发生可重试异常,也没有作用
和他配合的另外一个参数retry backoff.ms 两次重试的间隔,这个也很重要,应该根据实际业务来

1.4 ack

参考博客link

  • ack=1 leader副本成功写入消息代表发送成功。 消息丢失的场景,比如1.发送途中发现 LeaderNotAvailableException,如果就一个副本,或者正在选举中,这个时候也没有重试机制,那么就会发生丢失 2. 成功写入leader副本,但是这个时候发生leader副本宕机,这个时候ISR 副本还没有进行消息同步,也会发生消息丢失。
  • ack=0,无需确认,最大吞吐量设置
  • ack=-1 所有ISR副本都写入成功,最强可靠性,但是也不是不会丢消息,后面会补充

1.5 kafka消息大小参数

Kafka 消息大小相关参数设置,这篇博客讲解的非常详细。

  • max.request.size :默认是1MB 限制发送请求大小
  • message.max.bytes:这个是ProducerBatch大小

个人感觉kafka的关于消息大小的参数太复杂,分为消费者端、服务这段、Broker端,如果没有把握,千万不要乱动

二、 原理分析

在这里插入图片描述

2.1 主线程

主线程主要是把消息进行进行编排,为批量发送做准备。
可能经过的步骤

  • 拦截器
  • 序列化器
  • 分区器

必经过的步骤就是在消息累加器中进行编排
编排的规则是按照topic的分区进行的,每个分区用双端队列进行存储,这也是kafka并不是完全的消息有序,只是分区消息有序的原因,进过编排后形成一个批次 ProducerBatch,每个 ProducerBatch是由ProducerRecord组成,既然设计了消息消息累加器,那么必定为有参数控制这个大小,他就是buffer.memory(默认32M). 如果主线程的速度太快,sender线程完全跟不上,这个时候消息累加器已经会满,这个时候有两个选择抛出异常等待sender线程消费,这个是有max.block.ms参数来控制的

重要参数batch.size

ProducerBatch 大小和 batch size 参数也有着密切的关系。当一条消息(ProducerRecord ) 流入 RecordAccumulator 时,会先 找与消息分区所对应的双端队列(如果没有则新建),再从这个双端队列的尾部获取一个 ProducerB atch (如果没有则新建),查看 ProducerBatch 中是否还可以写入这个 ProducerRecord ,如 果可以 写入,如果不可 以则 需要 建一个新Producer Batch 。在新建 ProducerBatch 评估这条消息的大小是否超过 batch size 参数大小,如果不超过,那么就以 batch size 参数的大 来创建 ProducerBatch ,这样在使用完这段内存区域之后,可以通过 BufferPool 的管理来进行 用;如果超过,那么就以评估的大小来ProducerBatch 这段内存区域不会被复用。

也就是说ProducerBatch大小不是固定的,但是如果大小是batch.size,那么会更高效,因为会复用

2.2 sender线程

比较特殊的是第7步骤InFlightRequest,这个就是控制kafka异步发送消息的ack机制,如果ack=0或者-1的时候,是需要确认的,这个时候是根据node节点(也就是broker节点)进行区分,每个node节点都会把request进行编排,数量由max.in.flight.requests.per. connection(默认是5)来控制的,超过这个数量的request就会等待发送直到前面5个有了响应并删除的时候,编排好之后,就可以发送了,如果哪个发送成功了会向InFlightRequest进行确认,然后删除掉已经响应成功的。

三、 kafka完全顺序

Kafk 可以保证同一个分区中的消息是有序的。如果生产者按照一定的顺序发送消息,那么这些消息也会顺序地写入分区,进而消费者也可以按照同样的顺序消费它们。对于某些应用来说,顺序性非常重要 ,比如 MySQL binlog 输,如果出现错误就会造成非常严重的后果果将 acks 参数配置为非零值,并且 max.flight.requests.per.connection 参数配置为大于1 的值,那么就会出现错序的现象 如果第一批次消息写入失败 而第二批次消息写入成功,那么生产者会重试发送第一批次的消息, 此时如果第一 次的消息写入成功,那么这两个批次的消息就出现了错序 一般而言,在需要保证消息顺序的场合建议把参数 max .flight.requests per connection 配置为1 ,而不是把 acks=0 配置为这样也会影响整体的吞吐。

总结下来就是

  • 分区数量设置为1
  • max.in.flight.requests.per.connection设置为1

重点补充一下
在这里插入图片描述
如果设置打于1,那么每次重试可能存在从新排序(乱序)的情况,比如我设置为5,那么我传输的过程应该是1,2,3,4,5 但是如果网络波动导致3丢失,那么kafka自动重试只会拉取3,也就是排序就成了1,2,4,5,3
所以,记得将每个批次的消息数设置为1,防止出现重试乱序的情况.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值