一、副本分配
1、副本分配原则
- 将副本平均分配给Broker
- 对于分配给特定的Broker分区,该分区的其他副本分布在其他Broker上
- 如果所有Broker都有机架信息,则尽可能将每个分区的的副本分配给不同的机架
2、无机架
- 从Broker列表中随机选取一个Broker作为起始位置,通过轮询分配每个分区的第一个副本
- 以增加位移的方式为每个分区分配剩余的副本
- 如下图,3个分区,3个副本。第一个Leader分区被分配到broker1上,那么其他两个分区会分配到broker2和broker3上
3、有机架
- 如果配置了机架,就不是按照broker顺序来了,而是按照交替机架的方式来选择broker。例如broker0、broker1、broker2放置在同一个机架1上,broker3、broker4、broker5放置在同一个机架2上。分区的选择不是按照0、1、2、3、4、5这样的顺序进行选择,而是按照0、3、1、4、2、5这样的顺序进行选择,然后应用简单的循环分配方式。
- 这样做的好处是:如果有机架下线,仍然能够保证可用性。
如图,分配5个分区三个副本的方式如下:
二、存储原理
-
Kafka中消息是以topic进行分类的,生产者通过topic向Kafka broker发送消息,消费者通过topic读取数据。然而topic在物理层面又能以partition为分组,一个topic可以分成若干个partition,partition还可以细分为segment,一个partition物理上由多个segment组成
- 每个segment有.log和.index文件
.index为索引文件,格式:offset: 1003476 position: 16377
.log为数据文件,格式:baseOffset: 1002567 lastOffset: 1003476 …省略… position: 16377 …省略…
每条消息都有一个offset,Consumer查找offset是通过二分法依据文件名去定位到哪个segment,匹配到对应offset的msg,然后解析msg。
修改segment大小到server.properties中修改,默认1G
-
这种相当于一个巨型文件被平均分配到多个大小相等的segment数据文件中(每个segment 文件中消息数量不一定相等)这样也方便old segment的删除,即方便已被消费的消息的清理,提高磁盘的利用率。
-
如上图:index索引文件存储大量的元数据,log数据文件存储大量的消息,索引文件中的元数据指向对应数据文件中message的物理偏移地址。其中以“.index”索引文件中的元数据(3, 348)为例,在“.log”数据文件表示第3个消息,即在全局partition中表示170410+3=170413个消息,该消息的物理偏移地址为348。
三、副本同步
-
同时满足下面两个条件的节点称为“同步”节点。Leader会跟踪同步节点,如果Follower宕机、卡住或者掉队,则Leader会将其从同步副本队列(ISR)中移除。
-
如何确定副本卡住和滞后是由副本lag.time.max.ms配置控制的
条件:
- 节点必须能够与ZK保持会话(Zookeeper的心跳机制)
- 如果是Follower,则必须复制发生在Leader上的写入,并且不能落后太远
3.同步流程
- HW和LEO相等,此时表示Leader没有新写入的消息。Follower已经完全追赶上Leader。
- 当有新消息写入时,Leader会通知Follower同步消息
- 以上图为例,Leader收到4、5、6三条消息,Follower1同步了4和5,而Follower2还没同步到任何消息。此时LEO的位置就是最后一条消息6,而由于2个Follower没有完全同步,这时HW仍然为3
- 如果在这个过程中Follower2同步超过replica.lag.time.max.ms设置的时间,Follower会被移出ISR队列。这时只有Leader和Follower1在ISR队列中,此时HW为5,LEO为6,consumer可以消费1-5共5条消息
- 经过一段时间所有的Follower都同步了Leader新收到的4、5、6三条消息,这时HW=LEO,Leader又继续等待消息写入
ps:
- 当Follower被Leader从ISR中移出,Follower副本对应的分区也就称之为同步失效分区,即under-replicated分区。
- 当一个故障副本被重启后,首先从磁盘上恢复最新的HW并将日志截断到HW。副本成为follower后,继续从leader那里获取HW以后的消息。一旦完全赶上leader,这个副本重新被加入到ISR中。系统将重新回到fully replicated模式