栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

kafka生产者的副本同步策略以及数据一致性、丢失消息、消息重复等问题的总结

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

kafka生产者的副本同步策略以及数据一致性、丢失消息、消息重复等问题的总结

前言

如果看官对一些基本术语不了解,请先翻阅

Kafka的架构模型以及工作流程_一念花开_的博客-CSDN博客

正文

在了解ISR之前,我们先了解kafka是如何保证数据可靠性的,以方便我们更好的理解ISR。

ACK应答机制

     为了保证数据可靠性,kafka使用了ack机制。

     当消息被生产者发送给kafka时,如果数据成功写入partition,需要给生产者发送ack,以此来确保消息被成功写入;如果生产者未收到ack,此消息会被producer重发;

     我们知道,Topic对应着多个Partition,而每个Partition都有副本,Partition的Leader负责处理读写消息事件,Follower负责同步Leader的数据,在leader故障时,能从Follower中选出新的Leader来接班;那么问题来了,什么时候发送ack?

      第一种方案:半数follower同步完成发送ack,优点相对于第二种方案来说只需要第二种方案时间的1/2即可完成同步,也就是延迟比全部完成数据同步再发送ack的方案要低一半;缺点也很明显,假设我们需要n个同步完成数据发送ack,那么我们总共需要2n+1个副本(follower一定不会在同一台机器)保证至少有一半以上的副本完成同步,2n+1个副本意味着重复数据多了两倍,我们知道kafka应用于大数据方面,两倍的数据量是无法忍受的,所以kafka选择了第二种方案,牺牲同步时间以换取空间;

      第二种方案:全部的follower都同步完成再发送ack,这种方案缺点很明显,就是花费同步的时间较多,优点也相对于半数机制来说,如果n台节点故障,我们只需要n+1台机器就能保证一定有一台机器完成副本同步,但我们仍然需要所有的副本同步消息再发送ack;

      现在的问题是,选择了第二种方案,如果有一台机器故障,Leader就要一直等待直到机器故障恢复且同步完成才能回复ack,为此kafka出现了ISR的说法。

 

 什么是ISR?

       ISR全称In-Sync-Replica-Set,就是与Leader保持数据同步的的follower集合,它由Leader动态维护,如果follower超过一定的时间阈值(参数replica.lag.time.max.ms)未与Leader同步数据,此follower将会被踢出ISR中。Leader只需要等待ISR中所有副本都同步完成即可回复producer ack。

再谈ACK

        ACK有三种机制

        1.acks=0,producer不等待ack,也就是数据发给partition就算完了,当机器故障时,存在丢数据的情况;

           (1)、数据发送给broker时,leader故障,由于不等待ack,没有重发机制,消息丢失

           (2)、数据发送给broker时,leader接收到了数据,follower还没同步数据,leader故障,也会导致消息丢失

        

        2.acks=1,producer等待ack,只要Leader写完数据就返回ack,不关心follower是否完成   同步,存在丢失数据情况;

         (1)、数据发送给broker时,leader写完了数据并返回ack,follower还没同步数据,leader故障,导致消息丢失

        3.acks=all,producer等待ISR的ack,ISR中所有的follower都同步完成数据才返回ack,存在重复数据、数据丢失的情况;

        此状态下有极端情况是:ISR中只剩一个Leader,此时acks=-1退化到acks=1,将有可能丢失数据。

        (1)、leader写完数据,ISR的follower也将数据同步完成时,leader故障,producer没收到ack,将数据重发,造成数据重复的情况

如何防止数据丢失与数据重复?

        在acks设置为all时,只要不退化到isr中只剩leader的情况(也就是acks=1时),那么就不会丢失数据,同时如果我们想要消息不重复怎么办?kafka为此添加了Producer的enable.idompotence参数(如果设置了此参数就无需再设置acks参数),将其设置为true表示开启幂等性,有了不丢失数据做保障再加上幂等性,就能保证数据不丢失也不重复。

       开启了幂等性之后的producer在连接broker时会被分配一个Producer ID,并且为每一个partition都维护一个顺序号Sequence Number,消息被发送到broker时会将Producer ID,Partition,Sequence Number做一个记录,如果有与之相同的消息再发进来,就会被认为是重复数据。

       如果Producer故障重启,Producer ID将会被重置,所以Kafka只能保证单分区、单会话的幂等性。如果想做到跨分区、跨会话的幂等性,可以使用事务,kafka在0.11版本引入了事务,它使其一组操作将具有原子性,要么全部成功要么全部失败、不会出现中间态的,且producer需要显示的指定txid,与producer id进行绑定,就算机器故障重启、也能通过txid还原pid,从而实现跨分区、跨会话的Exactly once。

 

       

   

        

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/573012.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号