概念

为保证producer发送的数据,能可靠的发送到指定的topic,topic的每个partition收到producer发送的数据后,都需要向producer发送ack(acknowledgement确认收到),如果producer收到ack,就会进行下一轮的发送,否则重新发送数据。
image.png

副本数据同步策略

延迟低 选举新的leader时,容忍n台节点的故障,需要2n+1个副本
选举新的leader时,容忍n台节点的故障,需要n+1个副本 延迟高

Kafka选择了第二种方案,原因如下:
1.同样为了容忍n台节点的故障,第一种方案需要2n+1个副本,而第二种方案只需要n+1个副本,而Kafka的每个分区都有大量的数据,第一种方案会造成大量数据的冗余。
2.虽然第二种方案的网络延迟会比较高,但网络延迟对Kafka的影响较小。

ISR

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

ack应答机制

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

acks参数配置


0:代表producer往集群发送数据不需要等到集群的返回,producer不等待broker的ack,不确保消息发送成功。安全性最低但是效率最高。这一操作提供了一个最低的延迟,broker一接收到还没有写入磁盘就已经返回,当broker故障时有可能丢失数据

先回答生产者(发送ack)再处理数据

生产者发送完了数据给broker,broker只要一接收到数据就返回ack给生产者, 最后broker自己把数据存到磁盘里面.万一broker挂掉了,此时还没来得及存入磁盘的数据就丢失了.

1:代表producer往集群发送数据只要leader应答就可以发送下一条,只确保leader发送成功。producer等待broker的ack,partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,那么将会丢失数据

生产者给Leader broker发送数据之后,Leaderbroker给数据放到内存里面, Leader发送ACK之后,如果此时Leader挂掉了,别的follower还没来得及同步数据,那么放到内存的数据照样丢失.此时会进行Leader选举,当生产者发送数据给新的Leader的时候,那么之前没来得及同步的数据就丢失了.

-1(all):代表producer往集群发送数据需要所有的follower都完成从leader的同步才会发送下一条,确保leader发送成功和所有的副本都完成备份。安全性最高,但是效率最低。producer等待broker的ack,partition的leader和follower全部落盘成功后才返回ack。但是如果在follower同步完成后,broker发送ack之前,leader发生故障,那么会造成数据重复

这种配置之后Kafka数据百分之百不会丢失,生产者将数据发送给Leader broker的时候 ,Leader broker 会立马通知follower broker 去同步数据,都同步完了数据落入磁盘之后,Leader broker才会将ack返回给生产者, 这种是百分之百不会丢失数据的,但是会出现数据重复的情况.
造成数据重复的原因是:
producer往 broker集群里面写一条消息,消息内容为”hello”, 此时leader收到消息了,然后让follower同步这条消息,此时 follower也同步完了这个消息.此时本来leader应该发送ack给producer,但是此时leader挂掉了,没来得及发送ack,
由于选举机制,其中一台follower会选举变成leader,此时producer由于长时间没有接收到ack,又会尝试重新发送那条消息,消息内容还是”hello”,如果broker集群没有宕机的话,那么此时这条消息就重复了.就有两个”hello”了