4.Kafka生产者

分类栏目:Kafka

资讯

生产者发送流程:

Kafka的Producer可以同步或异步发送消息.在消息发送的过程中,涉及到了两个线程-----main线程和sender线程,以及一个线程共享变量--RecordAccumulator. main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到kafka broker.


 

分区好处:

a.便于合理使用存储资源,每个Partition在一个Broker上存储,可以把海量的数据按照分区切割成一块一块数据存储在多台Broker上。合理控制分区的任务,可以实现负载均衡。
b.提高并行度,生产者可以以分区为单位发送数据;消费者可以以分区为单位进行消费数据
 

分区策略:

方便在集群中扩展:每个partion可以通过调整以适应它所在的机器,而一个topic又可以有多个partition组成,因此整个集群就可以适应任意大小的数据了.

可以提高并发:因为可以以partition为单位读写了.

 

 分区的原则:

我们需要将Producer发送的数据封装成一个ProducerRecord对象.

A:指明partition的情况下,直接将指明的值直接作为partition值;

B:没有指明partition值但有key的情况下,将key的hash值与topic的partition数进行取余得到partition值;

C:既没有partition值又没有key值的情况下,kafka采用StickyPartition(黏性分区器),会随机选择一个分区,并尽可能一直使用该分区,待该分区的batch已满或者已完成,kafka再随机一个分区进行使用. 例如:第一次随机选择0号分区,等0号分区当前批次满了(默认16k)或者linger.ms设置的时间到,kafka再随机一个分区进行使用(如果还是0会继续随机)

 

生产者如何提高吞吐量:

 

数据可靠性保障:

A:生产者发送数据到topic partition的可靠性保证

为保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到producer发送的数据后,都需要向producer发送ack响应,如果producer收到ack,说明消息发送成功,否则重新发送数据.

B:Topic partition存储数据的可靠性保证

副本数据同步策略

方案
优点
缺点
半数以上完成同步,就发送ack消息
延迟低
选举新的leader时,容忍n台节点的故障,需要2n+1个副本
全部完成同步,就会发送ack消息
选举新的leader时,容忍n台节点的故障,需要n+1个副本
延迟高
kafka采用了第二种方案,原因如下:
1.同样为了容忍n台节点的故障,第一种方案需要2n+1个副本,而第二种只需要n+1个副本,而kafka的每个分区都有大量的数据,第一种方案会造成大量数的冗余.
2.虽然第二种方案的网络延迟高,但网咯延迟对kafka的影响较小.
 

ISR

采用第二种方案后,设想下:leader收到数据,所有的follwer都开始同步数据,但有一个follwer因为某种故障,迟迟不能与leader进行同步,那leader就要一直等下去,直到它完成同步,才能发送ack.这个问题怎么解决呢?
Leader维护了一个动态的in-sync replica set (ISR),意为和leader保持同步的follwer集合.当ISR中的follower完成数据的同步之后,leader就会给producer发送ack.如果follower长时间未向leaer同步数据,则该follower将被踢出ISR,该时间阀值由replica.lag.time.max.ms参数设定.Leader发生故障后,就会从ISR中选举新的leader.
 

ACK应答级别

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

这一操作提供了一个最低的延迟,partition的leader接收消息还没有写入磁盘已经返回ack,当leader故障时有可能丢失数据.

partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,那么将会丢失数据.

partition的leader和follower全部写入磁盘成功后才发送ack,但是如果在follower同步完成后,broker发送ack之前,leader发生故障,那么会造成数据重复.

Exactly Once语义

将服务器的ack级别设置为-1,可以保证Producer到server之间不会丢失数据,即at least once语义.相对的,将服务器ack级别设置为0 ,可以保证生产者每条消息只会被发送一次,即at most once语义.
At least once可以保证数据不丢失,但是不能保证数据不重复;相对的 At most Once可以保证数据不重复,但是不能保证数据不丢失.但是,对于一些非常重要的信息,比如说交易数据,下游数据消费者要求数据即不重复也不丢失,即Exactly once语义. 在0.11版本前的kafka对此是无能为力的,只能保证数据不丢失,再在下游消费者对数据做全局去重.对于多个下游应用的情况,每个都需要做单独去重,这就对性能造成很大影响.0.11版本的kafka,引入了一项重大特性:幂等性.所谓幂等性就是指producer不论向server发送多少次重复数据,server端都只会持久化一条.幂等性结合at least once语义,就构成了kafka的exactly once语义.即At least once+ 幂等性=Exactly once.
要启用幂等性,只需要将producer的参数中enable.idempotence设置为true即可.kafka的幂等性实现其实就是将原来下游需要做的去重放在了数据上游.开启幂等性的producer在初始化的时候会分配一个pid,发往同一partition的消息会附带sequence number.而Broker端会对<pid,partition,seqnumber>做缓存,当具有相同主键的消息提交时,broker只会持久化一条.
但是PID重启就会变化,同时不同的partition也具有不同主键,所以幂等性无法保证跨分区跨会话的Exactly Once.