从概念、原理到架构设计,一次性搞清楚 Partition 到底是什么、解决了什么问题
Partition(分区)是 Kafka 中 最小的并行处理单元, 一个 Topic 可以拆成多个 Partition 并行读写, 每个 Partition 内部是一个 严格有序、只能追加写入(Append-Only)的日志文件(Commit Log)。
如果 Topic 只有一个分区,所有消息只能串行读写,吞吐量受限于单台机器的 I/O 和 CPU。 Partition 的本质就是分片(Sharding),把数据拆到多个机器上并行处理,突破单机瓶颈。
下方是 Kafka 集群的完整架构示意。点击 Partition 查看详情,拖动滑块调整分区数,观察数据如何分布。
每个 Partition 在物理上对应一个日志目录,目录下有多个 Segment 文件(.log + .index)。 消息只能追加到末尾,每条消息被分配一个唯一的 Offset(偏移量),从 0 开始递增。 Offset 是 Partition 内的全局唯一ID,Consumer 通过 Offset 追踪消费进度。
每个 Partition 有多个 Replica(副本),但只有 Leader Replica 对外提供服务(读写), 其余 Follower Replica 只负责从 Leader 拉取数据同步。 如果 Leader 挂了,Controller 会从 ISR(In-Sync Replicas)中选举新的 Leader。
Producer 发送消息时,通过 Partitioner 决定消息写入哪个 Partition。 不同的策略直接影响有序性和负载均衡。
// Kafka 默认分区策略(Java) // 1. 指定了 key → 按 key 的 hash 分配到固定 partition(保证同 key 有序) int partition = Utils.toPositive(Utils.murmur2(key)) % numPartitions; // 2. 没有 key → StickyPartition(尽量发往同一 partition,批次更大) // 3. 自定义 Partitioner class MyPartitioner implements Partitioner { public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) { // 自定义路由逻辑 return customRoute(key, cluster.partitionCountForTopic(topic)); } }
Kafka 保证:一个 Partition 同一时刻只能被一个 Consumer 消费。 Consumer Group 内的 Consumer 会均匀分配 Partition,实现并行消费。