Kafka-生产者消息缓存机制和发送应答机制

1、生产者消息缓存机制

生产者缓存机制的主要目的是将消息打包,减少网络IO频率。

Kafka生产者为了避免高并发请求对服务端造成过大压力,每次发消息时并不是一条一条发往服务端,而是增加一个高速缓存,将消息集中到缓存后,批量进行发送。这种缓存机制也是高并发处理时经常使用的一种机制。

Kafka的消息缓存机制涉及到KafkaProducer中的两个关键组件: accumulator 和 sender。

源码截图如下:

在这里插入图片描述

1.1、RecordAccumulator处理逻辑

RecordAccumulator,是Kafka生产者的消息累加器。KafkaProducer把要发送的消息先在ReocrdAccumulator中缓存起来,再分批发送给kafka broker。

在RecordAccumulator中,会针对每一个Partition,维护一个Deque双端队列,这些Dequeue队列基本上是和Kafka服务端的Topic下的Partition对应的。每个Dequeue里会放入若干个ProducerBatch数据。

KafkaProducer每次发送的消息,都会根据key分配到对应的Deque队列中。每个消息都会保存到队列中的某一个ProducerBatch中。消息分发的规则是由Partitioner组件完成。

主要涉及到两个参数:

  • BUFFER_MEMORY_CONFIG,RecordAccumulator缓冲区大小。
  • BATCH_SIZE_CONFIG, 缓冲区每一个batch的大小。

在配置类:ProducerConfig.java

1.2、Sender处理流程

Sender是KafkaProducer中用来发送消息的一个单独的线程。每个KafkaProducer对象都对应一个sender线程。它负责将RecordAccumulator中的消息发送给Kafka。

Sender每次只获取RecordAccumulator中缓存内容,达到BATCH_SIZE_CONFIG大小的ProducerBatch消息。如果消息比较少,ProducerBatch中的消息大小,在等待LINGER_MS_CONFIG(默认值 0)时长后,还达不到BATCH_SIZE_CONFIG的话,就直接将ProducerBatch中的消息读取出来。

Sender对读取出来的消息,以Broker为key,缓存到一个对应的队列当中。在队列中的消息称为InflightRequest。然后把这些消息发往Kafka对应的Broker中,直到收到Broker的响应,才会从队列中移除。

这些队列最多缓存MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION(默认值 5)个请求。

注意:一批消息是没有先后顺序的。

最后,Sender会通过其中的一个Selector组件完成与Kafka的IO请求,并接收Kafka的响应。

1.3、一些优化建议

Kafka的生产者缓存机制是Kafka面对海量消息时非常重要的优化机制。

合理优化参数,对于Kafka集群性能提升是非常重要的。

  • 如果消息体比较大,应该考虑加大batch.size,尽量提升batch的缓存效率。
  • 如果Producer要发送的消息确实非常多,需要考虑加大total.memory参数,尽量避免缓存不够造成阻塞。
  • 如果发现生产者发送消息比较慢,可以考虑提升max.in.flight.requests.per.connection参数,加大消息发送的吞吐量。
2、发送应答机制

在Producer把消息发送到Broker后,如何确定消息是否成功送达?

是通过在Producer端,设置属性acks

acks属性的作用是保证消息的安全性,尤其是在replica-factor备份因子比较大的Topic中。

acks属性三个值:

  • acks=0

    • 生产者不关心Broker端是否将消息写入到Partition。

    • 只发送消息,不关心应答。

    • 吞吐量最高,数据安全性最低。

  • acks=all 或 -1

    • 生产者需要等Broker端的所有Partiton都写完才返回结果。

    • 即Leader Partition以及其对应的Follower Partition都写完了,才能得到返回结果。

    • 数据最安全,吞吐量最低。因为每次发消息需要等待更长的时间。

  • acks=1

    • 一种相对中和的策略。

    • Leader Partition在完成自己的消息写入后,就向生产者返回结果。

2.1、代码实验

在消息生产者的demo代码加入acks属性代码,进行测试

// 参数值按测试需求变化而变 
props.put(ProducerConfig.ACKS_CONFIG, "1");

当设置acks=0时,代码运行效果:

在这里插入图片描述

当设置acks=all时,代码运行效果:

在这里插入图片描述

当设置acks=1时,代码运行效果:

在这里插入图片描述

从上面运行效果截图来年,当acks=0时,消息发送者拿不到offset的值。

参数设置建议:

  • acks=0,可靠性太差,很少使用。
  • acks=1,一般用于传输日志等,允许个别数据丢失的场景。使用范围最广。
  • acks=all或-1,一般用于传输敏感数据,比如与钱相关的数据。

补充说明:

如果acks=all或-1 ,Kafka并不是强制要求所有Partition都写入数据后才响应。

在Kafka的Broker服务端有一个配置参数min.insync.replicas,控制Leader Partition在完成多少个Partition的消息写入后,向Producer返回响应。

这个参数可以在config/server.properties文件中进行配置。

3、我的公众号&资料获取

敬请关注我的公众号:大象只为你,持续更新技术知识…

相关资料获取:

如需SpringKafka项目Demo,请后台回复:【springkafka】。

我的代码是基于SpringBoot3.x上写的,IDEA 2024版

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值