kafka 生产者

kafka producer 发送消息流程

在这里插入图片描述

在消息发送的过程中,涉及到了两个线程:main线程和Sender线程。main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到Kafka Broker

  • 主线程:main线程将消息发送给RecordAccumulator
  1. 封装消息对象ProducerRecord,然后调用send方法将数据发送出去
  2. 数据依次会进入拦截器、序列化器(将数据对象序列化)、分区器(计算数据应该发送到哪个分区。有几个分区,后续会创建几个队列)
  3. 随后数据会送往到内存缓存RecordAccumulator中(默认大小32m),然后将不同分区的数据封装到不同的Deque中
  • sender线程:Sender线程不断从RecordAccumulator中拉取数据发送到Kafka Broker(发送的条件为batch.size=16k,或者达到linger.ms的阈值)
  1. Producer客户端会发送Request请求到Kafka Broker,最多发送5个(由参数inflightrequests控制)。原因是,Producer客户端发送Request请求到Kafka Broker,理应上需要得到Kafka Broke中leader的ack应答,表示是否接收数据成功,但是为了考虑效率,Producer客户端可以暂时不必非要等到Kafka Broke中leader的ack,才去发送下一批数据,而是继续保持发送Request请求,发送数据给kafka集群,但是当发送的Request请求达到5个时,则就必须要求kafka集群返回ack应答了,否则将不会发送任何数据
  2. 请求发送过去以后,就开始传输数据了,数据是通过Selector进行传输的
  3. 数据到达kafka broker后,follwer就开始主动向leader同步数据,然后leader就会返回ack应答给Selector,告诉客户端这边数据是否同步数据成功。若成功,客户端这边就会删除对应的Request,再删除对应分区的数据;若失败,则客户端进行重试发送(重试次数int最大值)

kafka 异步发送和同步发送

send()方法处,涉及到异步发送和同步发送

  • 异步发送

异步发送又分为普通异步发送(默认方式)带回调函数callback的异步发送

普通异步发送

表现形式:send()

sender线程将数据从Deque中取出发送到kafka集群时,若不管Deque中的数据有没有真正的被送到kafka集群,源头数据依旧还源源不断的写入内存队列Deque中,这种方式被称之为异步发送

带回调函数callback的异步发送

表现形式:send(new callback())

触发时机:producer收到ack时

  • 同步发送

表现形式:send().get()

sender线程将数据从Deque中取出发送到kafka集群时,需要等内存队列中的数据被真正的被送到kafka集群后,源头数据才能继续被写入内存队列Deque中,这种方式被称之为同步发送

kafka 分区的好处

(1)方便在集群中扩展

每个Partition可以通过调整大小,以适应它所在的机器,而一个topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了

(2)可以提高并发

因为可以,以Partition为单位读写

kafka 分区的策略

kafka的分区器可以指定数据发送到broker的哪个分区,也可以不指定,这些都是由参数进行控制的

(1)参数中指明数据发送到哪个分区

(2)参数中没有指明数据发送到哪个分区,但指明了 key,这种情况下,将 key 的 hash 值与 topic 的 partition 数进行取余,然后决定将数据发送到哪个分区

(3)参数中既没有指明数据发送到哪个分区,又没有指明 key ,这种情况下,它会随机的将数据发送到一个分区,待该分区满后,会在随机选择一个分区

kafka 如何提高吞吐量

调整的是哪个阶段的参数:

在这里插入图片描述

都有哪些参数可调(具体调多少,需要进行测试)

1)32m缓存 =》 64m
2)批次大小默认16k => 32k
3)linger.ms 默认是0ms => 5-100ms
4)采用压缩 snappy zstd

kafka ISR

kafka 数据可靠性保证

数据完全可靠条件 = ACK设置为“-1” + 分区副本大于等于2 + ISR里应答的最小副本数量大于等于2

解释:

  1. 分区副本大于等于2—>数据2份以上才叫可靠
  2. ISR里应答的最小副本数量大于等于2—>意思是ISR中至少有1个leader和1个follower

kafka ACK应答机制

对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没必要等ISR中的follower全部接收成功,因此Kafka为用户提供了三种可靠性级别,用户根据对可靠性和延迟的要求进行权衡,选择以下的配置

acks参数配置:

0:producer不等待leader的ack,意思就是producer只管发数据给leader,不管leader是否将数据成功写入磁盘就离开了。如果leader接收到数据后,突然挂了,会导致丢失数据

1:producer等待leader落盘成功后返回ack,可靠性相对较高。如果在follower同步成功之前leader故障,那么将会丢失数据

-1(all):producer等待leader和ISR中所有follower落盘成功后返回ack,可靠性高,性能相对较慢。如果在follower同步完成后,leader发生故障,producer收不到leader的ack,那么随后它会重发数据,故会造成数据重复

如何选择ack级别:

在生产环境中,acks=0不用; acks = 1,一般用于传输普通日志,允许丢个别数据; ack = -1,一般用于传输和钱相关的数据,对可靠性要求比较高的场景

ack = -1
会造成数据的重复,而金融行业恰恰要求数据既不重复又不丢失,那需要怎么办?

那就需要生产者事务和幂等性的配合了,生产者事务和幂等性可以保证数据的精确

kafka 精确一次

Kafka 0.11版本以后,引入了一项重大特性:幂等性和事务。这两项的加持下,可以做到数据既不丢失,又不重复,俗称精确一次

kafka 幂等性

概念:幂等性就是指Producer不论向Broker发送多少次重复数据,Broker端都只会持久化一条,保证不重复

kafka为了实现幂等性,引入了《pid,分区号,序列号》,当发送数据时,会判读3者是否和上一批数据相同,若相同,则认为是同一批数据,然后过滤掉,否则,落盘数据

幂等性的缺点:

幂等性只能保证单会话内数据不重复。因为其中的PID,会当Kafka重启都会分配一个新的,且Sequence Number是单调自增的

怎么解决幂等性的缺点?

幂等性需要和事务进行配合,才能完全保证数据全局不重复

kafka 事务

内部原理

在这里插入图片描述

事务主要通过5个API来实现

// 1初始化事务
void initTransactions();

// 2开启事务
void beginTransaction() throws ProducerFencedException;

// 3在事务内提交已经消费的偏移量(主要用于消费者)
void sendOffsetsToTransaction(Map<TopicPartition, OffsetAndMetadata> offsets,
                              String consumerGroupId) throws ProducerFencedException;

// 4提交事务
void commitTransaction() throws ProducerFencedException;

// 5放弃事务(类似于回滚事务的操作)
void abortTransaction() throws ProducerFencedException;

kafka 至少一次、最多一次、精确一次

作用怎么做
至少一次可以保证数据不丢失,但是不能保证数据不重复至少一次(At Least Once) = ACK级别设置为-1 + 分区副本大于等于2 + ISR里应答的最小副本数量大于等于2
最多一次可以保证数据不重复,但是不能保证数据不丢失最多一次(At Most Once) = ACK级别设置为0
精确一次可以做到数据既不丢失,又不重复生产者幂等性+事务

kafka 如何保证数据有序

指定分区器只将数据送往到一个分区中。若送往到不同分区中,无法保证数据有序。如果就想要保证不同分区数据有序,只有在下游处理数据时,进行全局排序

kafka单分区内数据有一定有序吗?

sender线程那里最多帮我们缓存5个请求,5个请求在依次送往broker时,不一定都能一次性成功,若在发送第二个请求时失败了,重试后,就有可能排在第三个请求后,所以单分区内数据也有可能无序

如何保证kafka单分区内接收到的数据有序

1)设置max.in.flight.requests.per.connection=1,即设置为同步发送

2) 开启幂等性

在这里插入图片描述

原因说明:启用幂等性后,kafka服务端会在内存缓存producer发来的5个request的元数据信息,假设分别为request1、request2、request3、request4、request5,kafka服务端当接收到request1、request2时,会按照顺序进行落盘(根据幂等性原则),若此时request3没有及时到达kafka服务端,但request4、request5却到达了,那么kafka服务端会先让request4、request5进行等待,直到request3到达以后,才将所有的request按照顺序依次进行落盘

kafka 故障处理细节

(1)follower故障

follower发生故障后会被临时踢出ISR,待该follower恢复后,follower会读取本地磁盘记录的上次的HW,并将log文件高于HW的部分截取掉,从HW开始向leader进行同步,等该follower的LEO大于等于该Partition的HW,即follower追上leader之后,就可以重新加入ISR了

(2)leader故障

leader发生故障之后,会从ISR中选出一个新的 leader,之后,为保证多个副本之间的数据一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader同步数据

注意:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值