kafka深入理解(二)kafka生产者

1、分区策略:
1)分区的原因:
(1)方便在集群中扩展,每个partition可以通过调整以适应它所在的机器,而一个topic又可以由多个partition组成,因此整个集群就可以适应任意大小的数据了。
(2)可以提高并发,因为可以以partition为单位进行读写了。

2)分区的原则:
在这里插入图片描述
(1)在指出了partition的情况下,直接将指明的值作为partition的值。
(2)没有指明partition值但是有key的情况下,将key的hash值与topic的partition数进行取余得到partition值。
(3)既没有指明partition值又没指出key的情况下,使用轮询算法。第一次加入的分区是随机的,后面进行轮询。

2)保证数据的可靠性
为了保证生产者发送的数据,能可靠地发送给指定的topic,Topic的每个partition收到生产者发送的数据后,都需要向生产者发送一个ack(确认收到),如果生产者收到ack就会进行下一轮的数据发送,否则就会重新发送该数据。
在这里插入图片描述
这里又会衍生出以下两个问题
(1)何时发送ack:当确保有follower和leader同步完数据后,leader才能发送ack,这样才能保证leader挂了之后数据的安全性。

(2)有多少follower同步完成后,leader才发送ack呢?全部的follower都同步完成吗?部分follower同步完成?
在这里插入图片描述
kafka选择了第二种方案,全部的follower同步完成才会让leader发送ack。因为,第一种方案为了容忍n台节点的故障需要维护2n+1个副本,而第二种方案只需要维护n+1台副本。kafka的每个分区都会有大量数据,第一种方案会造成大量数据的冗余。第二种方案可能会造成网络延迟,但是网络延迟对kafka来说影响较小。

ISR
采用第二种方案后,设想以下的场景:leader收到数据,follower开始同步数据,但是有一台或几台follower发送故障,无法同步完成,这样leader就不能发送ack给生产者。这个问题怎么解决?

Leader维护了一个动态的ISR,意为与leader保持同步的follower集合。当ISR中的follower完成数据同步后,Leader就会给生产者发送ack。如果follower长时间未和leader同步数据,leader就会将该follower踢出ISR的队伍,该时间阈值由replica.lag.max.ms参数设定。leader发生故障后会从ISR集合中选出新的leader.

ack应答机制:
对于某些不太重要的数据,对数据的可靠性要求不太高,所以没必要等ISR中的follower全部同步完。kafka为用户提供了三种可靠性级别,根据用户对可靠性和延迟的要求进行权衡,选择配置。

ack参数配置:
acks的参数可以设置为“0”,“1”,“-1”。

0::生产者不需要等待broker的ack,broker一接收到还没有写入磁盘就已经返回,当broker故障时可能丢失数据。就是生产者直接发送数据,不需要接受返回的ack。

1::生产者等待broker的ack,partition的leader落盘成功后返回ack,如果follower在同步成功之前,leader发送故障,那么将会丢失数据。

-1::生产者等待broker的ack,partition的leader和follower全部落盘成功后才会返回ack.如果在follower同步完成后,broker发送ack之前,leader发送故障,那么会造成数据重复。

故障处理细节:
在这里插入图片描述
LEO:指的是所有副本中最大的offset
HW:指的是消费者所能见到的最大的offset,也即ISR队列中最小的LEO

(1)follower故障:当follower发生故障时会被临时提出IST队列,待该follower恢复后,follower会读取本地磁盘记录的上次的HW,并将log文件中高于HW的部分截去,从HW开始向Leader同步。等待该follower的LEO大于等于该partititon的HW,即follower追上leader后,就可以重新加入该ISR了。

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

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

Exactly Once语义:
将服务器的ACK级别设置为-1的话,可以保证producer到server之间不会丢失数据,即at least once。相对的将ACK的级别设置为0的话,可以保证每条消息只发送一次,即at most once语义。

at least once语义可以保证数据不丢失,但是不能保障数据不重复。at most once语义可以保证数据不重复,但是不能保障数据不丢失。但是对于一些特别重要的消息需要保障其不能重复也不能丢失,即Exactly Once语义。在0.01版之前的kafka对此是无能为力的,只能保证数据不丢失,再在下游消费者对数据做多重去重。对于多个下游应用的情况下,每个都需要单独做全局的去重,这样就对性能产生了很大的影响。

在0.11版本后的kafka,引入了一项重大特性:幂等性。幂等性就是生产者无论向server发送了多少重复数据,server端都只会持久化一条记录。幂等性结合at least once语义就构成了kafka的exactly once语义。即:
at least once + 幂等性 = exactly once
需要启动幂等性,只需要将producer的参数中的enable.idompotence设置为true即可。kafka的幂等性实现原理就是将原来下游需要做的去重工作放在了数据上游,这样就不需要重复地去重。开启幂等性后,生产者在初始化的时候就会分配一个pid,发往同一个partition的消息会附带swquence number。而broker端会对(pid,partititon,seqnumber)做缓存,当具有相同主键的消息提交时,broker只会持久化一条。
但是PID重启就会变化,同时不同的Partition也具有不同的主键,所以幂等性无法保证跨分区跨会话的exactly once,即生产者挂了之后再次启动会重新分配给该生产者一个id,这样主键就不同了,幂等性就无法保证数据的不重复了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值