kafka副本机制之数据可靠性
一、概述
为了提升集群的HA,Kafka从0.8版本开始引入了副本(Replica)机制,增加副本机制后,每个副本可以有多个副本,针对每个分区,都会从副本集(Assigned Replica,AR)中,选取一个副本作为Leader副本,所有读写请求都由Leader副本处理,其余的副本被称为Follwer副本,其会从Leader副本拉取消息更新到本地。因此,Follower更像是Leader的热备。
一般情况下,同一个分区的多个副本会被均匀的分配到集群中的不同Broker上,当leader副本所在机器出现故障后会重新选举出新的leader实现故障转移。(针对副本如何分配以避免单台机器上leader过多导致集群负载均衡不均及多副本在同一机器上等问题,不再本文的讨论范围内,感兴趣的小伙伴,可以参考下kafka-reassign-partitions脚本)。
二、关键术语
- 副本:kafka对消息的冗余存储以提升容灾能力,以分区为单位。
- Leader副本:每个分区都有多个副本,针对每个分区,都有一个唯一的一个Leader副本,负责该分区的读写请求处理。
- Follower副本:从Leader副本拉取数据,作为Leader副本的热备。
- AR:(Assigned Replica)副本集合(Leader+Follower的总和)
- ISR:(In-Sync Replica)同步副本集合,与leader副本消息镜像“相差”不多的副本集合,又称为“核心副本集”,与kafka 发送端的ACK的几种语义有关,后面会详聊(注意这个集合是动态的,是会剔除和新增的)。
- HW:(High Watermark)是一个特殊的标记,与ISR有关,用以标记该分区中哪些消息被“commit”了,自然的对于消费者来说,它只能看到被commit了的消息,也就是HW之前的消息,当ISR集合中的副本都从Leader拉取了HW之后的某些消息后,Leader才会递增HW,因此HW的概念仅存在与Leader副本中,Follower不存在这个概念。
- 有的小伙伴可能会问了,那为何要有这个标记呢,这个标记是为了从语义的角度保证即使Leader副本所在的机器宕机了,也不会出现消息丢失,后面会详细介绍。
- LEO:(Log End Offset)每个分区都会有的一个标记,标示当前分区的最后一条消息(针对Leader就是Leader上的最后一条消息,针对某个Follower,就是当前该Follower的最后一条消息)
三、图解AR、ISR、HW、LEO
这里我们假设每个副本有三个分区,副本被剔除和加入ISR的临界条件为落后leader 三条消息,kafka判断是否符合ISR的条件有两个:
- Follower落后leader多少条消息,落后超过配置值后将踢出ISR
- Follwer多久没从leader同步消息,超过配置时间没拉取数据将从ISR踢出(kafka0.9后删除了该判断,a为唯一判断标准)。
下面我们用图来表达下上面的概念的关系:
- 时刻t1该分区的情况如下,此时ISR与AR一致(Leader,follower1,follower2),follower2 和 leader的消息一致,LEO都为4,follower1的LEO为2,因此leader的HW为2.
- .时刻t2 follower full gc.
- 时刻t3,leader接受producer发送来的2条消息5、6,此时发现Follower1已经落后了自己4条消息,将follower1踢出ISR集合
- 时刻t4,follower2 从leader拉取到5这条消息,更新HW值。
- 时刻t5,follower1 full gc完成后,发现自己已经落后了很多消息,开始从leader追消息,待消息不落后leader太多时,申请加入ISR中。
经过上面的图解分析后,我们来看下几个需要注意的点
- ISR是AR的一个子集,并且是不断伸缩的,变化的条件为“是否落后太多的消息”
- HW之前的消息代表被集群“commit”的消息,只有commit的消息才对client端(consumer以及request.required.acks为-1时的producer),在前面我们说过,这样能够使kafka在语义上支持不丢消息。我们从producer和consumer两个维度来分析:
在这之前,我们先说下request.required.acks的取值范围(1、0、-1)
1:leader成功就返回
0:无需等待leader响应
-1:ISR都成功才返回
- 从producer的角度:当producer将request.required.acks设置为-1时候,保证了消息已经在多个副本中存在了,此时即便leader挂了,这个消息还是存在的(leader选举会从ISR中选举出新的leader),那么假如ISR迟迟同步不成功怎么办呢?
- 从consumer的角度:如果没有HW,consumer拉取到最新的消息后,而此时leader宕机,很有可能新的leader中并没有此消息。
当然不能保证消息永远不会丢,极端的情况下,如ISR中只有leader的时候(当然可以配置集群可用的最小核心副本集个数,但会极大的损失可用性),或者所有副本都宕机了(这个。。。没办法。),消息还是会丢的。