为了保证producer的消息能可靠的投递到指定的topic,topic的每一个分区partition收到消息后,都须要向producer发送ack(acknowlege确认收到),若是生产者producer收到了ack,则进行下一轮的发送,不然从新发送。ide
ACK机制的实现
问题:分区中现有一个leader副本节点和多个follower副本节点,生产者将消息发送过来的时候,什么时候返回ack给生产者?3d
leader副本负责读与写,follower副本同步leader的数据。日志
方案1:leader和全部的follower都同步完成,才发送ack给生产者
方案2:leader+follower同步完成的数量过半,就发送ack给生产者blog
kafka采用的eader+follower彻底同步机制(ISR中follower),全部节点同步完成才返回ack。kafka
存在问题:leader+follower彻底同步时,假若有1个leader+4个follower,1个leader和3个follower都同步完成,1个follower同步超级慢或者挂掉,会影响返回或者不返回ack。同步
ISR机制的实现it
当leader挂掉的时候,由controller会在follower副本中选举出一个leader。可是这个剩余follower副本有一个条件,就是follower必须在ISR列表中。io
leader和ISR中的follower副本都同步完成时,就返回ack。class
ISR (IN-SYNC Replication) 维护了与leader信息一致的follower副本的信息,当leader挂掉的时候 就从这个ISR中选举。zookeeper
ISR信息存放在zookeeper的topic信息中,由kafka动态维护
leader如何动态维护ISR?
在0.9以后的版本中已经移除。
存在问题,生产者批量产生多余4000条的消息,发送给leader,此时ISR中全部的follower副本所有落后于leader,都会被剔除ISR。而后又要有新的follower副本加入ISR(问题:频繁操做ISR,还要操做zookeeper)。
生产者生产消息进行投递——>分区中的leader——>通知到ISR中全部的follower副本进行同步数据——>ISR中全部的follower告知leader同步完成——>leader返回ack——>生产者
[x] acks 生产者投递消息的ACK的级别设置
若是须要等到ISR全部的follower副本返回消息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回应会重试投递,会形成数据重复。
log中每一个消息都会有对应一个offset偏移量。
leader与ISR中全部的follower的文件的最小LEO为HW。如上图所示,HW为12。
对于消费者来讲,leader中不大与HW的数据才能被consumer可见。如图所示leader文件中的0~12能够被消费者所见。
leader选举机制的实现
图示HW为9,消费者只能看到0~9
假如leader挂掉了,选举follower2为leader,那么以新leader通知其余节点以HW 9为基准,超过HW的部分须要截取掉,leader自身的(LEO为11 大于HW 9)不用截取掉。而后重新的leader开始同步。
**