生产者分区原则
1.指定partition编号的情况下,直接将指明的值直接作为partition值
2.没有指明partition值但有key的情况下,将key的hash值与topic的partition数进行取余得到partition值
3.没有partition值也没有key值的情况下,第一次调用随机生成一个数,然后进行轮询。例如:201201201 这样的
ack参数设置:(保证生产者尽量不丢失数据)
值:
0 ; producer不等待broker的ack,这一操作提供了一个最低的延迟,broker一接收到还没有写入磁盘就已经返回,当broker故障时有可能丢失数据。
1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,那么将会丢失数据。
-1(all):producer等待broker的ack,partition的(ISR)leader和follower全部落盘成功后才返回ack,但是如果在follower同步完成后,broker发送ack之前,leader发生故障,那么会造成数据重复
故障处理机制:(保证消费者尽量不丢失数据)
Log文件中的HW和LEO
HW:所有副本中最小的LEO,(消费者能见到的最大的offset)
LEO:每个副本最大的offset值
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同步数据
注意:这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复。
Exactly Once 语义
将服务器的ACK级别设置为-1,可以保证Producer到server之间不会丢失数据,即At Least Once (至少一次)语义, 它可以保证数据不丢失,但是不能保证不重复。
将服务器ACK级别设置为0,可以保证生产者每条消息只会被发送一次,即At Most Once(至多一次) 语义 , 它可以保证数据不重复,但不能保证不丢失、
0.11版本的kafka,引入了幂等性;就是指Producer不论向server发送多少次重复数据,server端只会持久化一条。幂等性结合At Least Once语义,就构成了kafka的Exactly Once语义。
Exactly Once = At Least Once + 幂等性
要启用幂等性,只需要将Producer的参数中enable.idompotence设置为true即可(会把默认把ack设置为 -1), kafka的幂等性实现其实就是将原来下游需要做的去重工作放在了数据上游,开启幂等性的Producer在初始化的时候会被分配一个PID,发往同一partition的消息会附带Sequence Number,而Broker端会对<PID ,partition , SeqNumber>做缓存,当具有相同主键的消息提交时,Broker只会持久化一条。
当broker重启 PID就会变化,同时不同的partition也具有不同主键,所以幂等性无法保证跨分区回话的Exactly Once。
(也就是说,如果<PID ,partition , SeqNumber>三个值一模一样的时候就是会对数据进行去重,如果当broker重启后,那么就不会做去重操作了。)