kafka中的topic可以细分为不同的partition一个topic可以将消息存放在不同的partition中。leader和follower每个partition可以设置一个leader和多个follower。kafka的消息没有设置读写分离每个消息发送时都是发送至对应的partition的leader-paertionfollower-partition主要是为了备份数据而存在当leader-partition出现故障时数据已经完全同步的follower-partition也会切换成leader-partition。AR和ISRAR分区中所有的副本统称为AR。 ISR所有与leader节点保持同步的副本包括leader节点组成的节点生产者首先将消息发送给leader副本然后follower从leader中同步消息。 ISR是AR的子集。数据的存储在partition中一个topic中的数据存放在不同的partition中一个分区的内容会存储成一个log文件为了防止log过大引入了日志分段根据一定规则将log切分为多个logSegment相当于一个巨型文件被切分成了很多不同的文件。log和logSegment关系如下Log在物理上只以文件夹的形式存储,日志文件在磁盘的存储如下主题的分区数设置在server.properties配置文件中可以指定一个全局的分区数设置这是对每个主题下的分区数的默认设置默认是1。当然每个主题也可以自己设置分区数量如果创建主题的时候没有指定分区数量则会使用server.properties中的设置。代码语言javascriptAI代码解释bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic my-topic --partitions 2 --replication-factor 1在创建主题的时候可以使用--partitions选项指定主题的分区数量代码语言javascriptAI代码解释[rootlocalhost kafka_2.11-2.0.0]# bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic abc Topic:abc PartitionCount:2 ReplicationFactor:1 Configs: Topic: abc Partition: 0 Leader: 0 Replicas: 0 Isr: 0 Topic: abc Partition: 1 Leader: 0 Replicas: 0 Isr: 0分区多的优点kafka使用分区将topic的消息打散到多个分区分别保存在不同的broker上实现了producer和consumer消息处理的高吞吐量。Kafka的producer和consumer都可以多线程地并行操作而每个线程处理的是一个分区的数据。因此分区实际上是调优Kafka并行度的最小单元。对于producer而言它实际上是用多个线程并发地向不同分区所在的broker发起Socket连接同时给这些分区发送消息而consumer同一个消费组内的所有consumer线程都被指定topic的某一个分区进行消费。所以说如果一个topic分区越多理论上整个集群所能达到的吞吐量就越大。分区不是越多越好分区是否越多越好呢显然也不是因为每个分区都有自己的开销一、客户端/服务器端需要使用的内存就越多客户端producer有个参数batch.size默认是16KB。它会为每个分区缓存消息一旦满了就打包将消息批量发出。分区越多consumer端获取数据所需的内存越多。同时consumer线程数要匹配分区数(大部分情况下是最佳的消费吞吐量配置)的话那么这里面的线程切换的开销本身已经不容小觑了。服务器端的很多组件都在内存中维护了分区级别的缓存比如controllerFetcherManager等因此分区数越多这种缓存的成本就越大。二、文件句柄的开销每个分区在底层文件系统都有属于自己的一个目录。该目录下通常会有两个文件 base_offset.log和base_offset.index。Kafak的controller和ReplicaManager会为每个broker都保存这两个文件句柄(file handler)。很明显如果分区数越多所需要保持打开状态的文件句柄数也就越多最终可能会突破你的ulimit -n的限制。三、降低高可用性Kafka通过副本(replica)机制来保证高可用。具体做法就是为每个分区保存若干个副本(replica_factor指定副本数)。每个副本保存在不同的broker上。如果你有10000个分区10个broker也就是说平均每个broker上有1000个分区。此时这个broker挂掉了那么zookeeper和controller需要立即对这1000个分区进行leader选举。比起很少的分区leader选举而言这必然要花更长的时间并且通常不是线性累加的。如果这个broker还同时是controller情况就更糟了。如何确定分区数量呢可以遵循一定的步骤来尝试确定分区数创建一个只有1个分区的topic然后测试这个topic的producer吞吐量和consumer吞吐量。假设它们的值分别是Tp和Tc单位可以是MB/s。然后假设总的目标吞吐量是Tt那么分区数 Tt / max(Tp, Tc)说明Tp表示producer的吞吐量。测试producer通常是很容易的因为它的逻辑非常简单就是直接发送消息到Kafka就好了。Tc表示consumer的吞吐量。测试Tc通常与应用的关系更大 因为Tc的值取决于你拿到消息之后执行什么操作因此Tc的测试通常也要麻烦一些。kafka分区和消费者线程的关系1、要使生产者分区中的数据合理消费消费者的线程对象和分区数保持一致多余的线程不会进行消费会浪费2、消费者默认即为一个线程对象 3、达到合理消费最好满足公司消费者服务器数*线程数 partition个数生产者与分区多对多默认的分区策略是如果在发消息的时候指定了分区则消息投递到指定的分区如果没有指定分区但是消息的key不为空则基于key的哈希值来选择一个分区如果既没有指定分区且消息的key也是空则用轮询的方式选择一个分区分区与消费者多对一同一时刻一条消息只能被组中的一个消费者实例消费。消费者组订阅一个主题意味着主题下的所有分区都会被组中的消费者消费到并且主题下的每个分区只从属于组中的一个消费者不可能出现组中的两个消费者负责同一个分区。如果分区数大于或者等于组中的消费者实例数那么一个消费者会负责多个分区如果消费者实例的数量大于分区数有一些消费者是多余的一直接不到消息而处于空闲状态。即若consumer数量大于partition数量会造成限制的consumer产生浪费。若consumer数量小于partition数量会导致均衡失效其中的某个或某些consumer会消费更多的任务。为什么一个消费者可以消费多个分区但是一个分区不能被多个消费者消费呢就是要保证一个分区下的消息顺序性。倘若两个消费者负责同一个分区那么就意味着两个消费者同时读取分区的消息由于消费者自己可以控制读取消息的offset就有可能C1才读到2而C1读到1C1还没处理完C2已经读到3了则会造成很多浪费因为这就相当于多线程读取同一个消息会造成消息处理的重复且不能保证消息的顺序这就跟主动推送push无异。所以说消息积压的时候部署多台消费者实例是不能加快消费原有分区的消息的。最多增加到和partition数量一致超过的组员只会占用资源而不起作用。kafka官方文档https://kafka.apache.org/documentation.html#introduction通过在主题中具有并行性--分区--的概念Kafka能够为用户进程池提供排序保证和负载平衡。这是通过将主题中的分区分配给使用者组中的使用者来实现的这样每个分区就会被组中的一个消费者使用。通过这样做我们确保使用者是该分区的唯一读者并按顺序使用数据。由于有许多分区这仍然平衡了许多使用者实例的负载。但是请注意不能有比分区更多的使用者实例。消费者consumer分组group消费者从partition中消费数据consumer有group的概念每个group可以消费完整的一份topic中的数据。消费者分区分配策略range策略是默认的分配策略是基于每个主题的。1、range分配策略针对的是主题这里所说的分区指的某个主题的分区消费者值的是订阅这个主题的消费者组中的消费者实例2、首先将分区按数字顺序排行序消费者按消费者名称的字典序排好序3、然后用分区总数除以消费者总数。如果能够除尽平均分配若除不尽则位于排序前面的消费者将多负责一个分区假设有3个主题T1T2T3都有7个分区那么按照咱们上面这种Range分配策略分配后的消费结果如下消费者线程对应消费的分区序号C0-0T1012T2012T3012C1-0T134T234T334C1-1T156T256T356roundrobin轮询RoundRobin策略的原理是将消费组内所有消费者以及消费者所订阅的所有topic的partition按照字典序排序然后通过轮询算法逐个将分区以此分配给每个消费者。使用RoundRobin分配策略时会出现两种情况如果同一消费组内所有的消费者订阅的消息都是相同的那么 RoundRobin 策略的分区分配会是均匀的。如果同一消费者组内所订阅的消息是不相同的那么在执行分区分配的时候就不是完全的轮询分配有可能会导致分区分配的不均匀。如果某个消费者没有订阅消费组内的某个 topic那么在分配分区的时候此消费者将不会分配到这个 topic 的任何分区。因此在使用RoundRobin分配策略时为了保证得均匀的分区分配结果需要满足两个条件同一个消费者组里的每个消费者订阅的主题必须相同同一个消费者组里面的所有消费者的num.streams必须相等。我们分别举例说明第一种比如我们有3个消费者C0C1C2都订阅了2个主题T0 和 T1并且每个主题都有 3 个分区(p0、p1、p2)那么所订阅的所有分区可以标识为T0p0、T0p1、T0p2、T1p0、T1p1、T1p2。此时使用RoundRobin分配策略后得到的分区分配结果如下消费者线程对应消费的分区序号C0T0p0、T1p0C1T0p1、T1p1C2T0p2、T1p2第二种比如我们依然有3个消费者C0C1C2他们合在一起订阅了 3 个主题T0、T1 和 T2C0订阅的是主题T0消费者C1订阅的是主题T0和T1消费者C2订阅的是主题T0、T1和T2这 3 个主题分别有 1、2、3 个分区(即:T0有1个分区(p0)T1有2个分区(p0、p1)T2有3个分区(p0、p1、p2))即整个消费者所订阅的所有分区可以标识为 T0p0、T1p0、T1p1、T2p0、T2p1、T2p2。此时如果使用RoundRobin分配策略得到的分区分配结果如下消费者线程对应消费的分区序号C0T0p0C1T1p0C2T1p1、T2p0、T2p1、T2p2Sticky分配策略在kafka的0.11.X版本才开始引入的是目前最复杂也是最优秀的分配策略。S它的设计主要实现了两个目的如果这两个目的发生了冲突优先实现第一个目的分区的分配要尽可能的均匀分区的分配尽可能的与上次分配的保持相同。我们有3个消费者C0C1C2都订阅了2个主题T0 和 T1并且每个主题都有 3 个分区(p0、p1、p2)那么所订阅的所有分区可以标识为T0p0、T0p1、T0p2、T1p0、T1p1、T1p2。此时使用Sticky分配策略后得到的分区分配结果如下消费者线程对应消费的分区序号C0T0p0、T1p0C1T0p1、T1p1C2T0p2、T1p2看起来和前面RoundRobin分配策略一样但其实底层实现并不一样。这里假设C2故障退出了消费者组然后需要对分区进行再平衡操作。如果使用的是RoundRobin分配策略它会按照消费者C0和C1进行重新轮询分配再平衡后的结果如下消费者线程对应消费的分区序号C0T0p0、T0p2、T1p1C1T0p1、T1p0、T1p2但是如果使用的是Sticky分配策略再平衡后的结果会是这样消费者线程对应消费的分区序号C0T0p0、T1p0、T0p2C1T0p1、T1p1、T1p2Stiky分配策略保留了再平衡之前的消费分配结果并将原来消费者C2的分配结果分配给了剩余的两个消费者C0和C1最终C0和C1的分配还保持了均衡。这时候再体会一下sticky翻译为粘粘的这个词汇的意思是不是豁然开朗了。对于同一个分区而言有可能之前的消费者和新指派的消费者不是同一个对于之前消费者进行到一半的处理还要在新指派的消费者中再次处理一遍这时就会浪费系统资源。而使用Sticky策略就可以让分配策略具备一定的“粘性”尽可能地让前后两次分配相同进而可以减少系统资源的损耗以及其它异常情况的发生。分区Rebalance(再均衡)场景有新的消费者加入消费者群组已有的消费者退出消费者群组订阅的主题的分区发生变化Rebalance给消费者群组带来了高可用性与伸缩性但是在Rebalance期间消费者无法读取消息整个群组一小段时间不可用而且当分区被重新分配给另一个消费者时消费者当前的读取状态会丢失。消费者组广播模式如果想实现广播的模式就需要设置多个消费者组这样当一个消费者组消费完这个消息后丝毫不影响其他组内的消费者进行消费这就是广播的概念。1多个消费者组1个partition该topic内的数据被多个消费者组同时消费当某个消费者组有多个消费者时也只能被一个消费者消费如图4所示2多个消费者组多个partition该topic内的数据可被多个消费者组多次消费在一个消费者组内每个消费者又可对应该topic内的一个或者多个partition并行消费如图5所示参考Kafka分区与消费者的关系https://www.cnblogs.com/cjsblog/p/9664536.htmlKafka分区数与消费者个数https://www.jianshu.com/p/dbbca800f607https://blog.csdn.net/OiteBody/article/details/80595971kafka分区和消费者线程的关系https://blog.csdn.net/tankun940507994/article/details/72781996深入分析Kafka架构三消费者消费方式、三种分区分配策略、offset维护https://blog.csdn.net/qq_26803795/article/details/105562691kafka中partition数量与消费者对应关系以及Java实践https://www.tqwba.com/x_d/jishu/279556.html为什么不能有比分区更多的使用者实例https://stackoverflow.com/questions/25896109/in-apache-kafka-why-cant-there-be-more-consumer-instances-than-partitionskafka多个消费者消费一个topic_详细解析kafka之 kafka消费者组与重平衡机制https://blog.csdn.net/weixin_39737224/article/details/112073632