手打不易,如果转摘,请注明出处!
注明原文:
https://blog.csdn.net/q258523454/article/details/147466262
目录
topic分区数、pod数、concurrency 之间的关系
模拟场景1:topic分区=3, concurrency=1, pod=2
模拟场景2:topic分区=3, concurrency=3, pod=3
前言
首先我们明确以下几点:
1. 不同消费组之间的消费是独立的,即topic的同一条数据可以被不同的组消费,互不影响
打个比方:
多个消费组消费同一个 Topic 时,就像 “不同的人读同一本书,各自从自己的进度开始读”,互不影响。Kafka 中的数据不会因被消费而删除,而是像 “图书馆的书”,会保留直到超过借阅期限(例如7天)才被清理。既保证了消息可以被多个不同的业务模块消费,又避免了消息的重复消费和数据丢失问题。
2. 按照'分区独占原则',一般情况下,某个topic的1个分区只会被某个消费组下的1个pod的消费
3. 每个分区是一个独立的队列,消息按顺序追加到分区的末尾
情况1:消费组中Pod 数量 = Topic 分区数
特点:完美负载均衡
-
一对一匹配:每个Pod(分拣员)对应一个分区(传送带),每个分拣员只负责一条传送带。
-
效率均衡:所有分拣员都能工作,没有闲置,每个分拣员负担相同。
-
扩展性限制:如果传送带数量不变,增加分拣员也没用(多余的分拣员无法工作)。
例子:
-
场景:你有 4个传送带(分区),恰好有 4个分拣员(Pod)。
-
结果:
-
分拣员1负责传送带1,分拣员2负责传送带2,以此类推。
-
所有分拣员都在工作,效率最高。
-
如果传送带数量不变,再招1个分拣员也没用,他会“无事可做”。
-
情况2:消费组中Pod 数量 > Topic 分区数
特点:部分 Pod 闲置
特点:
-
资源浪费:多余的Pod(分拣员)无法分配到任何分区(传送带),只能“干等”。
-
冗余但无用:虽然多招了分拣员,但无法提升处理能力,反而浪费资源。
-
故障恢复优势:如果某个分拣员离职,其他闲置分拣员可以立即顶上。
例子:
-
场景:你有 3个传送带(分区),但招了 5个分拣员(Pod)。
-
结果:
-
只有3个分拣员被分配到传送带1、2、3,另外2个分拣员“闲着”。
-
如果某个分拣员宕机,闲置分拣员会立刻接手他的传送带(再平衡)。
-
但平时只有3个分拣员在工作,多出来的2个分拣员无法提升效率。
-
情况3:消费组中Pod 数量 < Topic 分区数
特点:部分 Pod 需消费多个分区
-
分区共享:某些Pod(分拣员)需要处理多个分区(传送带)。
-
负载均衡:某些分拣员负担更重。
-
可能成为瓶颈:如果分拣员太少,传送带太多,分拣员可能忙不过来。
例子:
-
场景:你有 5个传送带(分区),但只有 3个分拣员(Pod)。
-
结果:
-
分拣员1负责传送带1和2,分拣员2负责传送带3和4,分拣员3负责传送带5。
-
每个分拣员处理多个传送带,但总有人更忙(比如分拣员1处理2个传送带)。
-
如果某个分拣员“离职”(Pod宕机),其他分拣员会接管他的传送带,但整体效率可能下降。
-
情况4:特殊-消费组中Pod 数量 =1
特点:
-
独揽所有分区:无论有多少分区,唯一的Pod必须处理所有分区。
-
单点故障风险:如果Pod宕机,整个消费组停止,直到Pod恢复。
-
吞吐量受限:Pod处理能力可能成为瓶颈,尤其是分区数量多时。
例子:
-
场景: 3个传送带(分区),但招了 1个分拣员(Pod)。
-
结果:
-
这个Pod必须同时处理5个分区的所有订单消息。
-
如果Pod崩溃,所有处理暂停,直到Pod重启。
-
使用 轮询策略(RoundRobin) 或 范围策略(Range),Pod会均匀分配所有分区,但处理压力极大。
-
总结对比表
情况 | 特点 | 优缺点 | 适用场景 |
---|---|---|---|
Pod = 分区 | 一对一,均衡分配。 | 优点:效率高,资源利用率高。缺点:无法扩展(除非增加分区)。 | 高吞吐量场景,分区数量固定。 |
Pod < 分区 | 每个Pod处理多个分区,可能超负荷。 | 优点:节省资源。缺点:可能成为瓶颈,故障风险高。 | 资源有限,分区多于Pod。 |
Pod > 分区 | 多余Pod闲置,但可快速接管故障。 | 优点:高可用性。缺点:资源浪费,平时效率不提升。 | 需要高可用性,容忍资源浪费。 |
仅1个Pod | 独揽所有分区,单点故障风险。 | 优点:部署简单。缺点:吞吐低,故障即瘫痪。 | 测试环境或非核心业务。 |
topic分区数、pod数、concurrency 之间的关系
实际测试
假设有1个group,绑定了2个topic,分别是demo-topic-1(分区3)、demo-batch-topic-1(分区3)
修改'-Dserver.port=xxxx'来启动多个pod模拟集群
模拟场景1:topic分区=3, concurrency=1, pod=2
启动的时候kafka会自动分配分区
pod1: 被指定了如下分区
demo-group: partitions assigned: [demo-topic-1, demo-topic-0]
demo-group: partitions assigned: [demo-batch-topic-2]
pod2: 被指定了如下分区
demo-group: partitions assigned: [demo-topic-2]
demo-group: partitions assigned: [demo-batch-topic-1, demo-batch-topic-0]
每次produce发送消息,会指定到某个分区
例如:
向demo-batch-topic发送的时候,partition=2 会到pod1消费
向demo-batch-topic发送的时候,partition=0或1 会到pod1消费
模拟场景2:topic分区=3, concurrency=3, pod=3
即使指定单个pod用多个线程,但是kafka会尽可能的跨实例分配
pod1:
demo-group: partitions assigned: [demo-batch-topic-1]
demo-group: partitions assigned: [demo-topic-1]
pod2:
demo-group: partitions assigned: [demo-topic-2]
demo-group: partitions assigned: [demo-batch-topic-0]
pod3:
demo-group: partitions assigned: [demo-topic-0]
demo-group: partitions assigned: [demo-batch-topic-2]
其他场景
topic最大分片=3,concurrency=1
pod=1,concurrency=1: 总线程数1,相当于单线程消费3个分片
pod=2,concurrency=1: 总线程数2,相当于2个pod共同消费3个分片,其中1个pod单线程消费2个分片
pod=3,concurrency=1: 总线程数3,相当于3个pod共同消费3个分片,每个pod有1个线程消费1个分片(完美负载)
pod=4,concurrency=1: 有1个pod不会去消费(可以提升高可用,当其他pod挂掉后会接替——故障转移)
topic最大分片=3,concurrency=2
pod=2,concurrency=2: 总线程数4,其中1个pod的1个线程闲置
topic最大分片=3,concurrency=3
pod=3,concurrency=3: 总线程数9,kafka会尽量按pod均匀分配,理论上每个pod有1个线程消费1个分区(实际测试确实如此)
核心:看总线程数
关系总结
Pod × concurrency < 分区数: 部分pod的单个线程会同时消费多个分区,导致性能变慢
Pod × concurrency = 分区数: 每个分区都有单独线程处理
Pod × concurrency > 分区数: 多余线程会空闲,浪费资源
生产环境下的完美负载:当 concurrency=1, pod数>=分区, 此时每个分区会单独消费一个分区, 同时多出来的集群pod具备故障转移