kafka系列11——第5章1——分区

 🌈hello,你好鸭,我是Ethan,西安电子科技大学大三在读,很高兴你能来阅读。

✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。
🏃人生之义,在于追求,不在成败,勤通大道。加油呀!

🔥个人主页:Ethan Yankang
🔥推荐:史上最强八股文||一分钟看完我的几百篇博客

🔥温馨提示:划到文末发现专栏彩蛋   点击这里直接传送

🔥本篇概览:详细讲解了kafka系列11——第5章1——分区。🌈⭕🔥


【计算机领域一切迷惑的源头都是基本概念的模糊,算法除外】


🔥   微服务全集

🔥   kafka全集

🔥   前一篇章


🌈引出

Apache的kafka是一个分布式的消息发布订阅中间件。具有高吞吐、可扩展和容错性等特点。主要用于处理大规模的流式数据

本博客从各个方面详细讲解了kafka的机制,并实际上手使用之,好好学完定会习得大功。(bushi,上一次面试就噶在kafka上了,好好对待之。)


5章 分区

tips 学完这一章你可以 ***
深入学习 Kafka 分区的管理
包括:优先副本的选举、分区重新分配等
        Kafka可以将主题划分为多个分区( Partition ),会根据分区规则选择把消息存储到哪个分区中,只要 分区规则设置的合理,那么所有的消息将会被均匀的分布到不同的分区中,这样就实现了负载均衡 和水平扩展。另外, 多个订阅者可以从一个或者多个分区中同时消费数据,以支撑海量数据处理能力。
        顺便说一句,由于消息是以追加到分区中的,多个分区顺序写磁盘的总效率要比随机写内存还要高(引用Apache Kafka – A High Throughput Distributed Messaging System的观点),是 Kafka 高吞吐率的重要保证之一。


5.1 副本机制

        由于 ProducerConsumer都只会与Leader 角色的分区副本相连,所以 kafka 需要以集群的组织形式提供主题下的消息高可用。kafka 支持主备复制,所以消息具备高可用和持久性。
        一个分区可以有多个副本,这些副本保存在不同的broker 上。每个分区的副本中都会有一个作为Leader。当一个 broker 失败时, Leader 在这台 broker 上的分区都会变得不可用, kafka 会自动移除Leader,再其他副本中选一个作为新的 Leader
        在通常情况下,增加分区可以提供kafka 集群的吞吐量。然而,也应该意识到集群的总分区数或是单台服务器上的分区数过多,会增加不可用及延迟的风险。

【红色的为leader】


5.2 分区Leader选举

可以预见的是 , 如果某个分区的 Leader 挂了 , 那么其它跟随者将会进行选举产生一个新的 leader, 之后所有的读写就会转移到这个新的Leader , kafka , 其不是采用常见的多数选举的方式进行副本的 Leader 选举, 而是会在 Zookeeper上针对每个Topic维护一个称为ISR in-sync replica 已同步的副本)的集合 , 显然还有一些副本没有来得及同步。只有这个ISR 列表里面的才有资格成
leader( 先使用 ISR 里面的第一个,如果不行依次类推,因为ISR 里面的是同步副本,消息是最完整且各个节点都是一样的 ) 。 通过 ISR,kafka需要的冗余度较低,可以容忍的失败数比较高。假设某个 topic f+1 个副本, kafka 可以容忍 f 个不可用, 当然 , 如果全部 ISR 里面的副本都不可用 , 也可以选择其他可用的副本 , 只是存在数据的不一致。

        


5.3 分区重新分配

        我们往已经部署好的Kafka 集群里面添加机器是最正常不过的需求,而且添加起来非常地方便,我们需 要做的事是从已经部署好的Kafka 节点中复制相应的配置文件,然后把里面的 broker id 修改成全局唯一 的,最后启动这个节点即可将它加入到现有Kafka 集群中
        但是问题来了,新添加的Kafka 节点并不会自动地分配数据,所以无法分担集群的负载,除非我们新建 一个topic 。但是现在我们想手动将部分分区移到新添加的 Kafka 节点上, Kafka 内部提供了相关的工具 来重新分布某个topic 的分区。

具体步骤

第一步:我们创建一个有三个节点的集群
,详情可查看第九章集群的搭建
itcast@Server-node:/mnt/d/kafka-cluster/kafka-1$ bin/kafka-topics.sh --create --
zookeeper localhost:2181 --topic heima-par --partitions 3 --replication-factor 3
Created topic heima-par.

详情查看
itcast@Server-node:/mnt/d/kafka-cluster/kafka-1$ bin/kafka-topics.sh --describe
--zookeeper localhost:2181 --topic heima
-par
Topic:heima-par PartitionCount:3 ReplicationFactor:3 Configs:
Topic: heima-par Partition: 0 Leader: 2 Replicas: 2,1,0 Isr:
2,1,0
Topic: heima-par Partition: 1 Leader: 0 Replicas: 0,2,1 Isr: 0
Topic: heima-par Partition: 2 Leader: 1 Replicas: 1,0,2 Isr:
1,0,2
itcast@Server-node:/mnt/d/kafka-cluster/kafka-1$
从上面的输出可以看出heima-par 这个主题一共有三个分区,每个有三个副本
第二步:主题heima-par再添加一个分区
itcast@Server-node:/mnt/d/kafka-cluster/kafka-1$bin/kafka-topics.sh--alter--zookeeperlocalhost:2181--topicheima-pa
r--partitions4
WARNING:Ifpartitionsareincreasedforatopicthathasakey,thepartition
logicororderingofthemessageswillbeaffected
Addingpartitionssucceeded!
查看详情已经变成 4 个分区

itcast@Server-node:/mnt/d/kafka-cluster/kafka-1$ bin/kafka-topics.sh --describe
--zookeeper localhost:2181 --topic heima
-par
Topic:heima-par PartitionCount:4 ReplicationFactor:3 Configs:
Topic: heima-par Partition: 0 Leader: 2 Replicas: 2,1,0 Isr:
2,1,0
Topic: heima-par Partition: 1 Leader: 0 Replicas: 0,2,1 Isr: 0
Topic: heima-par Partition: 2 Leader: 1 Replicas: 1,0,2 Isr:
1,0,2
Topic: heima-par Partition: 3 Leader: 2 Replicas: 2,1,0 Isr:
2,1,0
这样会导致 broker2 维护更多的分区
第三步:再添加一个broker节点
查看主题信息

itcast@Server-node:/mnt/d/kafka-cluster/kafka-1$ bin/kafka-topics.sh --describe
-zookeeper localhost:2181 --topic heima-par
Topic:heima-par PartitionCount:4 ReplicationFactor:3 Configs:
Topic: heima-par Partition: 0 Leader: 2 Replicas: 2,1,0 Isr:
2,1,0
Topic: heima-par Partition: 1 Leader: 0 Replicas: 0,2,1 Isr: 0
Topic: heima-par Partition: 2 Leader: 1 Replicas: 1,0,2 Isr:
1,0,2
Topic: heima-par Partition: 3 Leader: 2 Replicas: 2,1,0 Isr:
2,1,0
从上面输出信息可以看出新添加的节点并没有分配之前主题的分区

第四步:重新分配
        现在我们需要将原先分布在broker 1-3 节点上的分区重新分布到 broker 1-4 节点上,借助 kafka
reassign-partitions.sh 工具生成 reassign plan ,不过我们先得按照要求定义一个文件,里面说明哪些 topic需要重新分区,文件内容如下:

itcast@Server-node:/mnt/d/kafka-cluster/kafka-1$ cat reassign.json
{"topics":[{"topic":"heima-par"}],
"version":1
}
        然后使用 kafka - reassign - partitions.sh 工具生成 reassign plan
bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --topics-to -move-json-file
reassign.json --broker-list "0,1,2,3" --generate
itcast@Server-node:/mnt/d/kafka-cluster/kafka-1$bin/kafka-reassign-
partitions.sh--zookeeperlocalhost:2181--topics-to
-move-json-filereassign.json--broker-list"0,1,2,3"--generate
Currentpartitionreplicaassignment
{"version":1,"partitions":[{"topic":"heima-par","partition":2,"replicas":[1,0,2],"log_dirs":["any","any","any"]},{"topic":"heima-
par","partition":1,"replicas":[0,2,1],"log_dirs":["any","any","any"]},
{"topic":"heima-par","partition":0,"replicas":[2,1,0],"log_dirs":
["any","any","any"]},{"topic":"heima-par","partition":3,"replicas":
[2,1,0],"log_dirs":["any","any","any"]}]}

Proposedpartitionreassignmentconfiguration
{"version":1,"partitions":[{"topic":"heima-par","partition":0,"replicas":[1,2,3],"log_dirs":["any","any","any"]},{"topic":"heima-
par","partition":2,"replicas":[3,0,1],"log_dirs":["any","any","any"]},
{"topic":"heima-par","partition":1,"replicas":[2,3,0],"log_dirs":
["any","any","any"]},{"topic":"heima-par","partition":3,"replicas":
[0,1,2],"log_dirs":["any","any","any"]}]}
        上面命令中
--generate 表示指定类型参数
--topics-to-move-json-file 指定分区重分配对应的主题清单路径

注意:
        命令输入两个JSON字符串,第一个JSON内容为当前的分区副本分配情况,第二个为重新分配的候 选方案,注意这里只是生成一份可行性的方案,并没有真正执行重分配的动作。

        我们将第二个JSON 内容保存到名为 result.json 文件里面(文件名不重要,文件格式也不一定要以 json 为 结尾,只要保证内容是json 即可),然后执行这些 reassign plan
重新分配JSON文件
{
"version": 1,
"partitions": [
{
"topic": "heima-par",
"partition": 0,
"replicas": [
1,
2,
3
],
"log_dirs": [
"any",
"any",
"any"
]
},
{
"topic": "heima-par",
"partition": 2,
"replicas": [
3,
0,
],
"log_dirs":["any",
"any",
"any"
]
},
{
"topic": "heima-par",
"partition": 1,
"replicas": [
2,
3,
0
],
"log_dirs": [
"any",
"any",
"any"
]
},
{
"topic": "heima-par",
"partition": 3,
"replicas": [
0,
1,
2
],
"log_dirs": [
"any",
"any",
"any"
]
}
]
}
执行分配策略

itcast@Server-node:/mnt/d/kafka-cluster/kafka-1$ bin/kafka-reassignpartitions.sh --zookeeper localhost:2181 --reassignm
ent-json-file result.json --execute
Current partition replica assignment
{"version":1,"partitions":[{"topic":"heima-par","partition":2,"replicas":
[1,0,2],"log_dirs":["any","any","any"]},{"topic":"heimapar","partition":1,"replicas":[0,2,1],"log_dirs":["any","any","any"]},
{"topic":"heima-par","partition":0,"replicas":[2,1,0],"log_dirs":
["any","any","any"]},{"topic":"heima-par","partition":3,"replicas":
[2,1,0],"log_dirs":["any","any","any"]}]}
Save this to use as the --reassignment-json-file option during rollback
Successfully started reassignment of partitions.

查看分区重新分配的进度:
itcast@Server-node:/mnt/d/kafka-cluster/kafka-1$bin/kafka-reassign-
partitions.sh--zookeeperlocalhost:2181--reassignment-json-fileresult.json--verify
Statusofpartitionreassignment:
Reassignmentofpartitionheima-par-3completedsuccessfully
Reassignmentofpartitionheima-par-0isstillinprogress
Reassignmentofpartitionheima-par-2isstillinprogress
Reassignmentofpartitionheima-par-1isstillinprogress
从上面信息可以看出 heima-par-3 已经完成,其他三个正在进行中。

5.4 修改副本因子

        Kafka 中的副本因子(Replication Factor)指的是一个主题(Topic)的每个分区(Partition)在集群中存储的副本数量。

场景

        实际项目中我们可能在创建topic 时没有设置好正确的 replication-factor ,导致 kafka 集群虽然是高可用 的,但是该topic 在有 broker 宕机时,可能发生无法使用的情况 topic 一旦使用又不能轻易删除重建, 因此动态增加副本因子就成为最终的选择。
        说明:kafka 1.0 版本配置文件默认没有 default.replication.factor=x , 因此如果创建 topic 时,不指定 – replication-factor , 默认副本因子为 1. 我们可以在自己的 server.properties 中配置上常用的副本因子,省去手动调整。例如设置default.replication.factor=3
首先我们配置 topic 的副本,保存为 json 文件:
{
"version":1,
"partitions":[
{"topic":"heima","partition":0,"replicas":[0,1,2]},
{"topic":"heima","partition":1,"replicas":[0,1,2]},
{"topic":"heima","partition":2,"replicas":[0,1,2]}
]
}
然后执行脚本 bin/kafka-reassign-partitions.sh --zookeeper localhost:2181 --reassignment-json-file
replication-factor.json --execute
itcast@Server-node:/mnt/d/kafka_2.12-2.2.1$ bin/kafka-reassign-partitions.sh --
zookeeper localhost:2181 --reassignment-json-file replication-factor.json --
execute
Current partition replica assignment
{"version":1,"partitions":[{"topic":"topic0703","partition":1,"replicas":
[1,0],"log_dirs":["any","any"]},{"topic":"topic0703","partition":0,"replicas":
[0,1],"log_dirs":["any","any"]},{"topic":"topic0703","partition":2,"replicas":
[2,0],"log_dirs":["any","any"]}]}
Save this to use as the --reassignment-json-file option during rollback
Successfully started reassignment of partitions.

验证

itcast@Server-node:/mnt/d/kafka_2.12-2.2.1$bin/kafka-topics.sh--describe--zookeeperlocalhost:2181--topictopic0703
Topic:topic0703 PartitionCount:3 ReplicationFactor:3 Configs:
Topic: topic0703 Partition: 0 Leader: 0 Replicas: 0,1,2 Isr: 0
Topic: topic0703 Partition: 1 Leader: 1 Replicas: 0,1,2 Isr: 1,0
Topic: topic0703 Partition: 2 Leader: 2 Replicas: 0,1,2 Isr: 2,0

5.5 分区分配策略

消费者消费分配示意

按照 Kafka 默认的消费逻辑设定一个分区只能被同一个消费组 内的一个消费者 消费。假设目前某消费组内只有一个消费者C0 ,订阅了一个 topic ,这个 topic 包含 7 个分区,也就是说
这个消费者 C0 订阅了 7 个分区,参考下图:
        此时消费组内又加入了一个新的消费者C1 ,按照既定的逻辑需要将原来消费者 C0 的部分分区分配给消 费者C1 消费,情形上图( 2 ),消费者 C0C1 各自负责消费所分配到的分区相互之间并无实质性的干 扰。
        接着消费组内又加入了一个新的消费者C2 ,如此消费者 C0 C1 C2 按照上图( 3 )中的方式各自负责 消费所分配到的分区。
        如果消费者过多,出现了消费者的数量大于分区的数量的情况,就会有消费者分配不到任何分区。参考 下图,一共有8个消费者, 7 个分区,那么最后的消费者 C7 由于分配不到任何分区进而就无法消费任何 消息。
        上面各个示例中的整套逻辑是按照Kafka 中默认的分区分配策略来实施的。 Kafka 提供了消费者客户端参数partition.assignment.strategy 用来设置消费者与订阅主题之间的分区分配策略。默认情况下,此参数的值为:org.apache.kafka.clients.consumer.RangeAssignor ,即采用 RangeAssignor 分配策略。
        除此之外,Kafka中还提供了另外两种分配策略: RoundRobinAssignor StickyAssignor 。消费者客户端参数partition.asssignment.strategy 可以配置多个分配策略,彼此之间以逗号分隔。

RangeAssignor分配策略

        参考源码:org.apache.kafka.clients.consumer.RangeAssignor
        RangeAssignor策略的原理是按照消费者总数和分区总数进行整除运算来获得一个跨度,然后将分区按 照跨度进行平均分配,以保证分区尽可能均匀地分配给所有的消费者。对于每一个topic , RangeAssignor策略会将消费组内所有订阅这个 topic 的消费者按照名称的字典序排序,然后为每个消费 者划分固定的分区范围,如果不够平均分配,那么字典序靠前的消费者会被多分配一个分区。
        假设n=分区数 /消费者数量,m=分区数%消费者数量,那么前m个消费者每个分配n+1个分区,后面的 (消费者数量-m)个消费者每个分配n个分区。
        假设消费组内有2 个消费者 C0C1 ,都订阅了主题 t0t1 ,并且每个主题都有 4 个分区,那么所订阅的 所有分区可以标识为:t0p0 t0p1t0p2t0p3t1p0t1p1t1p2t1p3 。最终的分配结果为:
消费者C0:t0p0、t0p1、t1p0、t1p1
消费者C1:t0p2、t0p3、t1p2、t1p3

假设上面例子中 2 个主题都只有 3 个分区,那么所订阅的所有分区可以标识为: t0p0 t0p1 t0p2
t1p0 t1p1 t1p2 。最终的分配结果为:
消费者C0:t0p0、t0p1、t1p0、t1p1
消费者C1:t0p2、t1p2
可以明显的看到这样的分配并不均匀,如果将类似的情形扩大,有可能会出现部分消费者过载的情况。

RoundRobinAssignor分配策略[轮询]

        参考源码:org.apache.kafka.clients.consumer.RoundRobinAssignor
        RoundRobinAssignor策略的原理是将消费组内所有消费者以及消费者所订阅的所有 topic partition 按 照字典序排序,然后通过轮询方式逐个将分区以此分配给每个消费者。RoundRobinAssignor 策略对应 的partition.assignment.strategy 参数值为: org.apache.kafka.clients.consumer.RoundRobinAssignor。
        假设消费组中有2 个消费者 C0 C1 ,都订阅了主题 t0 t1 ,并且每个主题都有 3 个分区,那么所订阅的 所有分区可以标识为:t0p0 t0p1 t0p2 t1p0 t1p1 t1p2 。最终的分配结果为
消费者C0:t0p0、t0p2、t1p1
消费者C1:t0p1、t1p0、t1p2
        如果同一个消费组内的消费者所订阅的信息是不相同的,那么在执行分区分配的时候就不是完全的轮询 分配,有可能会导致分区分配的不均匀。如果某个消费者没有订阅消费组内的某个topic,那么在分配分 区的时候此消费者将分配不到这个topic 的任何分区。
        假设消费组内有3 个消费者 C0 C1 C2 ,它们共订阅了 3 个主题: t0 t1 t2 ,这 3 个主题分别 1 2 、 3个分区,即整个消费组订阅了 t0p0t1p0t1p1t2p0t2p1t2p2 6 个分区。
        具体而言,消费者 C0订阅的是主题t0 ,消费者 C1 订阅的是主题 t0 t1 ,消费者 C2 订阅的是主题 t0 t1 t2 ,那么最终的分 配结果为:
消费者C0:t0p0
消费者C1:t1p0
消费者C2:t1p1、t2p0、t2p1、t2p2
可以看到 RoundRobinAssignor 策略也不是十分完美,这样分配其实并不是最优解,因为完全可以将分 区t1p1 分配给消费者 C1

StickyAssignor 分配策略
        参考源码:org.apache.kafka.clients.consumer.StickyAssignor
        Kafka从 0.11.x 版本开始引入这种分配策略,它主要有两个目的:
  1. 分区的分配要尽可能的均匀;
  2. 分区的分配尽可能的与上次分配的保持相同。
        当两者发生冲突时,第一个目标优先于第二个目标。鉴于这两个目标,StickyAssignor 策略的具体实现 要比RangeAssignor RoundRobinAssignor 这两种分配策略要复杂很多。
        假设消费组内有3 个消费者: C0 C1 C2 ,它们都订阅了 4 个主题: t0 t1 t2 t3 ,并且每个主题有 2 个分区,也就是说整个消费组订阅了t0p0 t0p1 t1p0 t1p1 t2p0 t2p1 t3p0 t3p1 8 个分 区。最终的分配结果如下:
消费者C0:t0p0、t1p1、t3p0
消费者C1:t0p1、t2p0、t3p1
消费者C2:t1p0、t2p1
假设此时消费者 C1 脱离了消费组,那么消费组就会执行再平衡操作,进而消费分区会重新分配。如果采 用RoundRobinAssignor 策略,那么此时的分配结果如下:
消费者C0:t0p0、t1p0、t2p0、t3p0
消费者C2:t0p1、t1p1、t2p1、t3p1
        如分配结果所示,RoundRobinAssignor 策略会按照消费者 C0 C2 进行重新轮询分配。而如果此时使用 的是StickyAssignor 策略,那么分配结果为:
消费者C0:t0p0、t1p1、t3p0、t2p0
消费者C2:t1p0、t2p1、t0p1、t3p1
        可以看到分配结果中保留了上一次分配中对于消费者C0 C2 的所有分配结果,并将原来消费者 C1 负 担” 分配给了剩余的两个消费者 C0 C2 ,最终 C0 C2 的分配还保持了均衡。

总结

本章讲解了对分区及副本的一系列操作,如分区副本机制、分区重新分配、修改副本因子等。


💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖

热门专栏推荐

🌈🌈计算机科学入门系列                     关注走一波💕💕

🌈🌈CSAPP深入理解计算机原理        关注走一波💕💕

🌈🌈微服务项目之黑马头条                 关注走一波💕💕

🌈🌈redis深度项目之黑马点评            关注走一波💕💕

🌈🌈JAVA面试八股文系列专栏           关注走一波💕💕

🌈🌈JAVA基础试题集精讲                  关注走一波💕💕   

🌈🌈代码随想录精讲200题                  关注走一波💕💕


总栏

🌈🌈JAVA基础要夯牢                         关注走一波💕💕  

🌈🌈​​​​​​JAVA后端技术栈                          关注走一波💕💕  

🌈🌈JAVA面试八股文​​​​​​                          关注走一波💕💕  

🌈🌈JAVA项目(含源码深度剖析)    关注走一波💕💕  

🌈🌈计算机四件套                               关注走一波💕💕  

🌈🌈数据结构与算法                           ​关注走一波💕💕  

🌈🌈必知必会工具集                           关注走一波💕💕

🌈🌈书籍网课笔记汇总                       关注走一波💕💕         



📣非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤收藏✅ 评论💬,大佬三连必回哦!thanks!!!
📚愿大家都能学有所得,功不唐捐!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值