**一、AR**
在Kafka中维护了一个AR列表,包括所有的分区的副本。AR又分为ISR和OSR。
AR = ISR + OSR。
AR、ISR、OSR、LEO、HW这些信息都被保存在Zookeeper中。
**1.ISR**
ISR中的副本都要同步leader中的数据,只有都同步完成了数据才认为是成功提交了,成功提交之后才能供外界访问。
在这个同步的过程中,数据即使已经写入也不能被外界访问,这个过程是通过LEO-HW机制来实现的。
**2.OSR**
OSR内的副本是否同步了leader的数据,不影响数据的提交,OSR内的follower尽力的去同步leader,可能数据版本会落后。
最开始所有的副本都在ISR中,在kafka工作的过程中,如果某个副本同步速度慢于replica.lag.time.max.ms指定的阈值,则被踢出ISR存入OSR,如果后续速度恢复可以回到ISR中。
**3.LEO**
LogEndOffset:分区的最新的数据的offset,当数据写入leader后,LEO就立即执行该最新数据。相当于最新数据标识位。
**4.HW**
HighWatermark:只有写入的数据被同步到所有的ISR中的副本后,数据才认为已提交,HW更新到该位置,HW之前的数据才可以被消费者访问,保证没有同步完成的数据不会被消费者访问到。相当于所有副本同步数据标识位。
在leader宕机后,只能从ISR列表中选取新的leader,无论ISR中哪个副本被选为新的leader,它都知道HW之前的数据,可以保证在切换了leader后,消费者可以继续看到HW之前已经提交的数据。
所以LEO代表已经写入的最新数据位置,而HW表示已经同步完成的数据,只有HW之前的数据才能被外界访问。
**5.HW截断机制**
如果leader宕机,选出了新的leader,而新的leader并不能保证已经完全同步了之前leader的所有数据,只能保证HW之前的数据是同步过的,此时所有的follower都要将数据截断到HW的位置,再和新的leader同步数据,来保证数据一致。
当宕机的leader恢复,发现新的leader中的数据和自己持有的数据不一致,此时宕机的leader会将自己的数据截断到宕机之前的hw位置,然后同步新leader的数据。宕机的leader活过来也像follower一样同步数据,来保证数据的一致性。
**二、生产者可靠性级别**
通过以上的讲解,已经可以保证kafka集群内部的可靠性,但是在生产者向kafka集群发送时,数据经过网络传输,也是不可靠的,可能因为网络延迟、闪断等原因造成数据的丢失。
kafka为生产者提供了如下的三种可靠性级别,通过不同策略保证不同的可靠性保障。
其实此策略配置的就是leader将成功接收消息信息响应给客户端的时机。
通过request.required.acks参数配置:
1:生产者发送数据给leader,leader收到数据后发送成功信息,生产者收到后认为发送数据成功,如果一直收不到成功消息,则生产者认为发送数据失败会自动重发数据。
当leader宕机时,可能丢失数据。
0:生产者不停向leader发送数据,而不需要leader反馈成功消息。
这种模式效率最高,可靠性最低。可能在发送过程中丢失数据,也可能在leader宕机时丢失数据。
-1:生产者发送数据给leader,leader收到数据后要等到ISR列表中的所有副本都同步数据完成后,才向生产者发送成功消息,如果一只收不到成功消息,则认为发送数据失败会自动重发数据。
这种模式下可靠性很高,但是当ISR列表中只剩下leader时,当leader宕机让然有可能丢数据。
此时可以配置min.insync.replicas指定要求观察ISR中至少要有指定数量的副本,默认该值为1,需要改为大于等于2的值
这样当生产者发送数据给leader但是发现ISR中只有leader自己时,会收到异常表明数据写入失败,此时无法写入数据,保证了数据绝对不丢。
虽然不丢但是可能会产生冗余数据,例如生产者发送数据给leader,leader同步数据给ISR中的follower,同步到一半leader宕机,此时选出新的leader,可能具有部分此次提交的数据,而生产者收到失败消息重发数据,新的leader接受数据则数据重复了。
**三、leader选举**
当leader宕机时会选择ISR中的一个follower成为新的leader,如果ISR中的所有副本都宕机,怎么办?
有如下配置可以解决此问题:
unclean.leader.election.enable=false
策略1:必须等待ISR列表中的副本活过来才选择其成为leader继续工作。
unclean.leader.election.enable=true
策略2:选择任何一个活过来的副本,成为leader继续工作,此follower可能不在ISR中。
策略1,可靠性有保证,但是可用性低,只有最后挂了leader活过来kafka才能恢复。
策略2,可用性高,可靠性没有保证,任何一个副本活过来就可以继续工作,但是有可能存在数据不一致的情况。
**四、kafka可靠性的保证**
At most once:消息可能会丢,但绝不会重复传输。
At least once:消息绝不会丢,但可能会重复传输。
Exactly once:每条消息肯定会被传输一次且仅传输一次。
kafka最多保证At least once,可以保证不丢,但是可能会重复,为了解决重复需要引入唯一标识和去重机制,kafka提供了GUID实现了唯一标识,但是并没有提供自带的去重机制,需要开发人员基于业务规则自己去重。
有疑问加站长微信联系(非本文作者)