熟悉 Kafka的同学肯定知道,每个主题有多个分区,每个分区会存在多个副本,本文今天要讨论的是这些副本是怎么样放置在 Kafka集群的 Broker 中的。

大家可能在网上看过这方面的知识,网上对这方面的知识是千变一律,都是如下说明的:

为了更好的做负载均衡,Kafka尽量将所有的Partition均匀分配到整个集群上。Kafka分配Replica的算法如下:

  • 将所有存活的N个Brokers和待分配的Partition排序

  • 将第i个Partition分配到第(i mod n)个Broker上,这个Partition的第一个Replica存在于这个分配的Broker上,并且会作为partition的优先副本

  • 将第i个Partition的第j个Replica分配到第((i + j) mod n)个Broker上

假设现在有5个 Broker,分区数为5,副本为3的主题,按照上面的说法,主题最终分配在整个集群的样子如下:

但事实真的是这样的吗?实际上如果真按照这种算法,会存在以下明显几个问题:

  • 所有主题的第一个分区都是存放在第一个Broker上,这样会造成第一个Broker上的分区总数多于其他的Broker,这样就失去了负载均衡的目的;

  • 如果主题的分区数多于Broker的个数,多于的分区都是倾向于将分区发放置在前几个Broker上,同样导致负载不均衡。

所以其实上面的算法不准确。严格来说,上面的算法只是Kafka分配分区的一种特例(下面介绍算法部分会说明)。下面我们来看看 Kafka 内部到底是如何将分区分配到各个 Broker 中的,其具体算法实现函数就是 assignReplicasToBrokers,如下:

从上面的算法可以看出:

  • 副本因子不能大于 Broker 的个数;

  • 第一个分区(编号为0)的第一个副本放置位置是随机从 brokerList 选择的;

  • 其他分区的第一个副本放置位置相对于第0个分区依次往后移。也就是如果我们有5个 Broker,5个分区,假设第一个分区放在第四个 Broker 上,那么第二个分区将会放在第五个 Broker 上;第三个分区将会放在第一个 Broker 上;第四个分区将会放在第二个 Broker 上,依次类推;

  • 剩余的副本相对于第一个副本放置位置其实是由 nextReplicaShift 决定的,而这个数也是随机产生的;

所以如果我们依次如下调用上面的程序,ret 变量的输出结果会如下:

注意,你运行上面的程序结果可能和我的不一样,因为上面算法中的 startIndex 和 nextReplicaShift 变量都是随机生成的。其实 Kafka 创建主题就是这么调用算法的(fixedStartIndex

和 startPartitionId都是使用默认值)。另外,第一个放置的分区副本一般都是 Leader,其余的都是 Follow 副本,也就是说,上面输出的List第一个元素就是 Leader 副本所在的 Broker 编号。

到这里我们应该知道,网上其他博客介绍的 Kafka 分区是如何分配到各个 Broker 上其实是将 startIndex 设置成 0, 同时 fixedStartIndex 设置成 1,这样本文最开头介绍的算法就对了。但其实 Kafka 内部并不是这样调用的,大家注意。

如果我们还考虑机架的话,情况就更复杂了。这里为了简便起见,我们假设startIndex = 4,fixedStartIndex = 1。现在如果我们有两个机架的 Kafka 集群,brokers 0,

1 和 2 同属于一个机架;brokers 3, 4 和 5 属于另外一个机架。现在我们对这些 Broker 进行排序:0, 3, 1, 4, 2, 5(每个机架依次选择一个Broker进行排序)。按照机架的 Kafka 分区放置算法,如果分区0的第一个副本放置到broker 4上面,那么其第二个副本将会放到broker 2上面,第三个副本将会放到 broker 5上面;同理,分区1的第一个副本放置到broker 2上面,其第二个副本将会放到broker 5上面,第三个副本将会放到 broker 0上面。这就保证了这两个副本放置到不同的机架上面,即使其中一个机架出现了问题,我们的 Kafka 集群还是可以正常运行的。现在把机架因素考虑进去的话,我们的分区看起来像下面一样:

从上图可以看出,只要上面其中一个机架没有问题,我们的数据仍然可以对外提供服务。这就大大提高了集群的可用性

Kafka创建Topic时如何将分区放置到不同的Broker中的更多相关文章

  1. Kafka创建Topic时如何将分区放置到不同的Broker中?

    副本因子不能大于 Broker 的个数: 第一个分区(编号为0)的第一个副本放置位置是随机从 brokerList 选择的: 其他分区的第一个副本放置位置相对于第0个分区依次往后移.也就是如果我们有5 ...

  2. kafka创建topic,生产和消费指定topic消息

    启动zookeeper和Kafka之后,进入kafka目录(安装/启动kafka参考前面一章:https://www.cnblogs.com/cici20166/p/9425613.html) 1.创 ...

  3. kafka创建topic异常

    问题描述: kafak运行在weblogic账户下,jdk1.8,当在root账户下创建topic(当前账户下的jdk1.6)导致创建topic失败 ./bin/kafka-topics.sh --c ...

  4. kafka创建topic报错

    kafka执行如下创建topic的语句: [root@node01 kafka_2.11-1.0.0]# bin/kafka-topics.sh --create --topic streaming- ...

  5. Kafka如何创建topic?

    Kafka创建topic命令很简单,一条命令足矣:bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-facto ...

  6. Kafka设计解析(十)Kafka如何创建topic

    转载自 huxihx,原文链接 Kafka如何创建topic? 目录 一.命令行部分 二.后台逻辑部分 Kafka创建topic命令很简单,一条命令足矣: bin/kafka-topics. --re ...

  7. kafka的topic和分区策略——log entry和消息id索引文件

    Topic在逻辑上可以被认为是一个在的queue,每条消费都必须指定它的topic,可以简单理解为必须指明把这条消息放进哪个queue里. 为了使得Kafka的吞吐率可以水平扩展,物理上把topic分 ...

  8. kafka删除topic的方法及我在kafka上边的一些经验

    我在本地做kafka的producer调试,每隔一段时间后,所使用的topic管道就会堆积数据,而且我这边使用的是  kafka   bin 下的consumer命令单独消费的,每次都是  --fro ...

  9. kafka AdminClient 闲时关闭连接

    AdminClient 类提供了创建.删除 topic 的 api. 在项目中创建了一个 AdminClient 对象,每次创建 topic 时,调用 org.apache.kafka.clients ...

随机推荐

  1. MDX Cookbook 01 - Skipping Axis 合理使用空的 SET 集合获取全部层次结构成员

    假设我们只想显示一些与数据没有任何关联的维度成员信息,并且希望它们能够以行集的形式来显示,那么在 MDX 中就应该直接显示 ROWS  AXIS (1) 并且忽略掉 COLUMNS AXIS(0).比 ...

  2. sublime text 3-right click context menu

    dd a system wide windows explorer button " Edit with Sublime" similar to how Notepad++ doe ...

  3. android的activity被杀死后如何重启

    最近公司的大屏展示机器人上的程序运行时间长了,比如五天,十天会出现偶尔的崩溃,查日志可能是内存溢出或者是ndk层的错误,这种错误一时也不太好查找,但是产品那边有个要求就是程序退出了一定要能重启,能抓日 ...

  4. PySpark 的背后原理

    文章正文 Spark主要是由Scala语言开发,为了方便和其他系统集成而不引入scala相关依赖,部分实现使用Java语言开发,例如External Shuffle Service等.总体来说,Spa ...

  5. 彻底理解js中的闭包

    闭包是js的一个难点也是它的一个特色,是我们必须掌握的js高级特性,那么什么是闭包呢?它又有什么用呢? 我们都知道,js的作用域分两种,全局和局部,基于我们所熟悉的作用域链相关知识,我们知道在js作用 ...

  6. 物联网架构成长之路(7)-EMQ权限验证小结

    1. 前言 经过前面几小节,讲了一下插件开发,这一小节主要对一些代码和目录结构进行讲解,这些都是测试过程中一些个人经验,不一定是官方做法.而且也有可能会因为版本不一致导致差异. 2. 目录结构 这个目 ...

  7. Android adb input 命令介绍

    input命令是用来向设备发送模拟操作的命令: 因为版本不同,input命令也有所不同 以下为Android 4.0的input命令: usage:input text <string> ...

  8. Clustered Shading架构实现步骤

    最终决定越过Forward+,一步到位,直接调整至更先进的Clustered架构.步骤如下: 里程碑1:以CPU方式实现Light Culling,旨在理念验证,并与D3D10兼容里程碑2:以GPU ...

  9. Linux下ip地址查询

    [时间:2016-12] [状态:Open] [关键词:linux,ip地址,ifconfig,ip addr] 0 引用 说起来比较搞笑,我在windows下知道可以使用ipconfig命令查询本机 ...

  10. oracle删除数据库中的所有表

    连接:http://linben.blog.51cto.com/6205951/1293619 1.先禁用数据库中所有的约束 select 'alter table ' || table_name | ...