【Kafka】原理分析:分区副本机制

布满荆棘的人生 2022-12-21 06:00 348阅读 0赞

1.副本机制

Kafka的每个topic都可以分为多个Partition,并且多个partition会均匀分布在集群的各个节点下。虽然这种方式能够有效的对数据进行分片,但是对于每个partition来说,都是单点的,当其中一个partition不可用的时候,那么这部分消息就没办法消费。

所以kafka为了提高partition的可靠性而提供了副本的概念(Replica),通过副本机制来实现冗余备份。

  • 一主多从:每个分区可以有多个副本,并且在副本集合有1个leader副本,和多个follower副本组成;

    • 所有的读写请求都是由leader副本来进行处理。
    • follower副本会从leader副本同步消息日志

高可用 ——> 集群架构 ——> 主从模式。kafka集群的主从与zk集群的主从对比:

  • zookeeper集群

    • 是宏观的主从,即整体是一个大集群,leader是相对于所有zookeeper而言
    • 主从目的是负载均衡,采用读写分离(主写从读)
    • 问题是是主从要强一致可能带来的同步问题;
  • kafka集群

    • 是微观的主从,即每个partition都是一个小集群,leader只是相对于当前分区的副本们而言
    • 主从目的是为了备份Partition的数据;因为kafka通过对一个topic下的消息分区存储,再Consumer按区消费,就已经实现了负载均衡
    • 问题是数据丢失风险(可能多个分区的leader在一台机器上)
  • 分机分布:一般情况下,一个broker最多只有一个副本,同一个分区的多个副本会被均匀分配到集群中不同broker
  • 自动选举:当leader副本所在的 broker出现故障后,可以重新选举新的leader副本继续对外提供服务。

通过这样的副本机制来提高 kafka集群的可用性。
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzkzNTkyNw_size_16_color_FFFFFF_t_70_pic_center

2.副本创建

2.1 创建带副本topic

通过下面的命令去创建共3个副本的topic(replication-factor=3 )

  1. sh kafka-topics.sh
  2. --create
  3. --zookeeper localhost:2181
  4. --partitions 3
  5. --replication-factor 3 # 创建3个副本
  6. --topic secondTopic

2.2 获取leader信息

kafka集群中的一个broker中最多只能有一个副本,leader副本所在的broker节点的分区叫leader节点,follower副本所在的broker节点的分区叫follower节点。

如何知道那个各个分区中对应的leader是谁呢?可以从以下两个地方获取

  1. 在zookeeper上获取, 比如获取secondTopic第1个分区的状态信息。

    get /brokers/topics/secondTopic/partitions/1/state

    —> {“controller_epoch”:12,”leader”:0,”version”:1,”leader_epoch”:0,”isr”:[0,1]}

  2. 在kafka上获取

    sh kafka-topics.sh —zookeeper localhost:2181 —describe —topic test_partition

leader表示当前分区的leader是那个broker-id。下图中。绿色线条的表示该分区中的leader节点。其他节点就为follower

3.副本协同

Kafka分区下有可能有很多个副本(replica)用于实现冗余,从而进一步实现高可用。副本根据角色的不同可分为2类:

  • leader副本

    • 响应clients端读写请求的副本 ,消息的读写操作都会由leader节点来接收和处理

      注:Producer发来消息后,是leader收到直接返回还是等follower副本同步了再返回,由Producer的acks设置决定

    • 负责维护和跟踪ISR中所有follower滞后的状态,若follower副本出现异常,比如宕机、网络断开等原因长时间没有同步到消息,leader将把它踢出去。
  • follower副本

    • 拉取写入leader副本中的数据,不能响应clients端读写请求(仅作为备份用)

      注:同步过程会有一定的延迟,导致follower副本中保存的消息略少于leader副本,但只要未超出阈值都可容忍

    • leader挂了以后的选举由follower产生

3.1 同步标志

每个Kafka副本对象都有两个重要的属性:LEO和HW。注意是所有的副本,而不只是 leader副本。

  • LEO:即日志末端位移(log end offset),记录了该副本底层日志(log)中下一条消息的位移值。注意是下一条消息!也就是说,如果LEO=10,那么表示该副本保存了10条消息,位移值范围是[0, 9]。另外, leader LEO和follower LEO的更新是有区别的。
  • HW:即水位值(hight water)。小于等于HW值的所有消息都被认为是“已备份”的。对于同一个副本对象而言,其HW值不会大于LEO值。同理,leader副本和follower副本的HW更新是有区别的

在这里插入图片描述

从生产者发出的一条消息首先会被写入分区的leader 副本,不过还需要等待ISR集合中的所有 follower副本都同步完之后才能被认为已经提交,之后才会更新分区的HW,进而消费者可以消费到这条消息。

随着follower副本不断和leader副本进行数据同步,follower 副本的LEO会主键后移并且追赶到leader副本,这个追赶上的判断标准是当前副本的LEO是否大于或者等于leader副本的HW,这个追赶上也会使得被踢出的follower副本重新加入到ISR集合中。

注:若图中最右侧的follower副本被踢出ISR集合,也会导致这个分区的HW发生变化,变成 3

3.2 ISR队列

ISR(in-Sync replicas , 副本同步队列):包含了leader副本和所有与leader副本保持同步的follower副本(高级备胎们)。

表示目前“可用且消息量与leader相差不多的副本集合,这是整个副本集合的一个子集”。怎么去理解可用和相差不多这两个词呢?具体来说,ISR集合中的副本必须满足两个条件

  1. 副本所在节点必须维持着与zookeeper的连接
  2. 副本最后一条消息的offset与leader副本的最后一条消息的offset之间的差值不能超过指定的阈值

    • follower副本把leader副本LEO之前的日志全部同步完成时,则认为follower副本已经追赶上了leader 副本,这个时候会更新这个副本的lastCaughtUpTimeMs标识。
    • kafka副本管理器会启动一个副本过期检查的定时任务,这个任务会定期检查当前时间与副本的lastCaughtUpTimeMs的差值是否大于参数 replica.lag.time.max.ms 的值,若大于,则会把这个副本踢出ISR集合

另外,ISR数据保存在Zookeeper的 /brokers/topics/<topic>/partitions/<partitionId>/state 节点中

篇幅原因,关于分区副本协同的更详细过程请看下篇【Kafka】原理分析:详解副本协同流程…

4.副本选举

在ISR中至少有一个follower时,Kafka可以确保已经commit的数据不丢失,但如果某个Partition的所有Replica都宕机了,就无法保证数据不丢失了。有以下两种选举新leader策略

  1. 等待ISR中的任一个Replica“活”过来,并且选它作为Leader

    问题:如果一定要等待ISR中的Replica“活”过来,那不可用的时间就可能会相对较长。而且如果ISR中的所有 Replica都无法“活”过来了,或者数据都丢失了,这个Partition将永远不可用。

  2. 选择第一个“活”过来的Replica(不一定是ISR中的)作为Leader

    问题:选择第一个“活”过来的Replica作为Leader,若这个Replica不是ISR中的Replica,那即使它并不保证已经包含了所有已commit的消息,它也会成为Leader而作为consumer的数据源(所有读写都由Leader完成)

这就需要在可用性和一致性当中作出一个简单的折中。Kafka多采用第一种策略。

发表评论

表情:
评论列表 (有 0 条评论,348人围观)

还没有评论,来说两句吧...

相关阅读

    相关 kafka手动调整分区副本

    前言 在生产环境中,akfka集群下的每台服务器的配置和性能可能不一样,但Kafka集群只会根据配置规则创建对应的分区副本,这样一来可能就会导致个别服务器存储压力较大。

    相关 kafka消息分区机制原理

    背景 kafka如何支撑海量消息的集中写入? 答案就是消息分区。 核心思想是:负载均衡,采用合适的分区策略把消息写到不同的broker上的分区中; 其它的产品中有类

    相关 kafka副本机制

    Kafka允许topic的分区拥有若干副本,这个数量是可以配置的,你可以为每个topci配置副本的数量。Kafka会自动在每个个副本上备份数据,所以当一个节点down掉时数据依