为了保证producer的消息能可靠的投递到指定的topic,topic的每个分区partition收到消息后,都需要向producer发送ack(acknowlege确认收到),如果生产者producer收到了ack,则进行下一轮的发送,否则重新发送。

kafka消息分发和消费策略(生产者消息投递可靠性)(1)

ACK机制的实现

问题:分区中现有一个leader副本节点和多个follower副本节点,生产者将消息发送过来的时候,何时返回ack给生产者?

leader副本负责读与写,follower副本同步leader的数据。

方案1:leader和所有的follower都同步完成,才发送ack给生产者

方案2:leader follower同步完成的数量过半,就发送ack给生产者

kafka消息分发和消费策略(生产者消息投递可靠性)(2)

kafka采用的eader follower完全同步机制(ISR中follower),所有节点同步完成才返回ack。

存在问题:leader follower完全同步时,假如有1个leader 4个follower,1个leader和3个follower都同步完成,1个follower同步超级慢或者挂掉,会影响返回或者不返回ack。

ISR机制的实现

当leader挂掉的时候,由controller会在follower副本中选举出一个leader。但是这个剩余follower副本有一个条件,就是follower必须在ISR列表中。

leader和ISR中的follower副本都同步完成时,就返回ack。

ISR (IN-SYNC Replication) 维护了与leader信息一致的follower副本的信息,当leader挂掉的时候 就从这个ISR中选举。

ISR信息存放在zookeeper的topic信息中,由kafka动态维护

kafka消息分发和消费策略(生产者消息投递可靠性)(3)

leader如何动态维护ISR?

kafka消息分发和消费策略(生产者消息投递可靠性)(4)

在0.9之后的版本中已经移除。

存在问题,生产者批量产生多余4000条的消息,发送给leader,此时ISR中所有的follower副本全部落后于leader,都会被剔除ISR。然后又要有新的follower副本加入ISR(问题:频繁操作ISR,还要操作zookeeper)。

生产者生产消息进行投递——>分区中的leader——>通知到ISR中所有的follower副本进行同步数据——>ISR中所有的follower告知leader同步完成——>leader返回ack——>生产者

优点:延迟性最低

缺点:如果接收到消息后leader没有写入磁盘就挂掉,从ISR中的follower新选举leader后,会丢失数据。

问题:leader写入磁盘完成后挂掉了,ISR中的follower还没有来得及同步。从ISR中的follower新选举leader后,会丢失数据。

消费者投递消息后,等待leader和ISR中所有的follower副本同步完成,leader才返回ack。

优点:leader和ISR中所有的follower都同步完成,不丢数据,达到副本数据一致性。

问题:leader在返回ack之前就挂掉了,会从ISR中的follower中选出leader,此时所有leader follower数据都一致。生产者没有收到leader的ack回应会重试投递,会造成数据重复。

kafka消息分发和消费策略(生产者消息投递可靠性)(5)

log中每个消息都会有对应一个offset偏移量。

leader与ISR中所有的follower的文件的最小LEO为HW。如上图所示,HW为12。

leader选举机制的实现

图示HW为9,消费者只能看到0~9

假如leader挂掉了,选举follower2为leader,那么以新leader通知其他节点以HW 9为基准,超过HW的部分需要截取掉,leader自身的(LEO为11 大于HW 9)不用截取掉。然后从新的leader开始同步。

来源:https://www.tuicool.com/articles/JrYB3qA

欢迎关注微信公众号【慕容千语】

,