Skip to content

Kafka 入门指南

Kafka 基础概念

核心概念

┌─────────────────────────────────────────────────────────────────┐
│                      Kafka 核心架构                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   Producer ──▶ Topic ──▶ Partition ──▶ Consumer Group            │
│                              │                                  │
│                              ├── Partition 0                    │
│                              ├── Partition 1                    │
│                              └── Partition 2                    │
│                                                                  │
│   每个 Partition 有多个副本,分布在不同 Broker                     │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
概念说明
Producer消息生产者
Consumer消息消费者
Consumer Group消费者组,同一组内消息只被消费一次
Topic消息主题
Partition分区,实现水平扩展
BrokerKafka 服务节点
Replica副本,保证高可用

💡 实战场景

  • 日志收集:Flume → Kafka → Hadoop
  • 消息系统:订单通知、事件驱动
  • 流处理:实时数据分析

消息可靠性

ACK 机制

💡 实战场景:下单支付后,系统需要确保消息不丢失

bash
# Producer 发送消息的确认级别
acks=0    # 不等待Leader确认,可能丢失消息
acks=1    # Leader 确认收到即可
acks=all  # 所有 ISR 副本确认

# ISR (In-Sync Replicas)
// Leader 保持同步的副本集合
min.insync.replicas=2  # ISR 最小数量
┌─────────────────────────────────────────────────────────────────┐
│                      消息可靠性等级                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   acks=0  ⭐☆☆☆☆  最快,可能丢失                             │
│   acks=1  ⭐⭐⭐☆☆  平衡,默认选择                             │
│   acks=all ⭐⭐⭐⭐⭐ 最安全,性能最低                          │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

面试点:⭐⭐⭐⭐⭐ 实战重要性:⭐⭐⭐⭐⭐


消费者组

消费者组机制

┌─────────────────────────────────────────────────────────────────┐
│                    消费者组分区分配                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   Topic: my-topic (3 partitions)                                │
│                                                                  │
│   Consumer Group A:                                              │
│   ┌─────────┐  ┌─────────┐  ┌─────────┐                        │
│   │C1 (P0) │  │C2 (P1) │  │C3 (P2) │                        │
│   └─────────┘  └─────────┘  └─────────┘                        │
│   每个 Consumer 消费一个 Partition                               │
│                                                                  │
│   Consumer Group B:                                              │
│   ┌─────────┐  ┌─────────┐  ┌─────────┐                        │
│   │C4 (P0,1)│  │C5 (P1) │  │C4 (P2) │                        │
│   └─────────┘  └─────────┘  └─────────┘                        │
│   2个 Consumer 消费3个 Partition                                │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
java
// 消费者组
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("my-topic"));

// 同一组内分区分配
while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
    for (ConsumerRecord<String, String> record : records) {
        System.out.println(record.value());
    }
}

特点

  • 同一组内 Consumer 不能消费同一 Partition
  • 不同组可以重复消费同一消息
  • Partition 数量决定最大并行度

分区策略

分区分配规则

java
// 1. 指定 partition
producer.send(new ProducerRecord<>("topic", partition, key, value));

// 2. 按 key 哈希
producer.send(new ProducerRecord<>("topic", key, value));
// key 相同 → 相同 partition(保证顺序)

// 3. 轮询(无 key)
producer.send(new ProducerRecord<>("topic", value));

💡 实战场景:保证同一订单的消息有序

java
// 按订单 ID 哈希,保证同一订单的消息在同一 Partition
producer.send(new ProducerRecord<>("order-events", orderId, orderMessage));

消息顺序性

单 Partition 顺序保证

┌─────────────────────────────────────────────────────────────────┐
│                      消息顺序场景                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   订单流程(必须有序):                                          │
│   1. 创建订单 → 2. 支付 → 3. 发货 → 4. 签收                   │
│                                                                  │
│   解决方式:                                                     │
│   - 相同订单 ID 发到同一 Partition                               │
│   - 单 Partition 单 Consumer                                    │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘
java
// 按 key 发送到同一分区,保证同一 key 消息顺序
producer.send(new ProducerRecord<>("order-topic", orderId, message));

// 消费者按偏移量顺序消费
while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
    for (ConsumerRecord<String, String> record : records) {
        // 按顺序处理
    }
}

面试点:⭐⭐⭐⭐ 实战重要性:⭐⭐⭐⭐


消费者位移管理

位移提交

java
// 自动提交(默认)
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "5000");

// 手动提交
props.put("enable.auto.commit", "false");
while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));

    for (ConsumerRecord<String, String> record : records) {
        process(record);
    }

    // 手动提交
    consumer.commitSync();
}

消息传递语义

┌─────────────────────────────────────────────────────────────────┐
│                      消息传递语义                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   at most once(最多一次)                                      │
│   - 异步提交,可能丢失消息                                       │
│   - Consumer 先提交 offset,再处理消息                           │
│                                                                  │
│   at least once(至少一次)                                     │
│   - 同步提交,可能重复消费                                       │
│   - Consumer 先处理消息,再提交 offset                           │
│                                                                  │
│   exactly once(精确一次)                                      │
│   - 事务机制                                                   │
│   - Producer + Consumer 事务                                    │
│   - 用于支付等关键场景                                          │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

分区副本

副本机制

┌─────────────────────────────────────────────────────────────────┐
│                      Partition 副本分布                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   Partition 0:                                                   │
│   ┌─────────────────────────────────────────────────────────┐  │
│   │  Leader: Broker-1   ISR: [Broker-1, Broker-2]          │  │
│   │  Follower: Broker-2 (同步中)                            │  │
│   └─────────────────────────────────────────────────────────┘  │
│                                                                  │
│   Partition 1:                                                   │
│   ┌─────────────────────────────────────────────────────────┐  │
│   │  Leader: Broker-2   ISR: [Broker-2, Broker-3]          │  │
│   │  Follower: Broker-3 (同步中)                            │  │
│   └─────────────────────────────────────────────────────────┘  │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

LEO 和 HW

  • LEO (Log End Offset):当前分区写入消息的最大 offset
  • HW (High Watermark):已同步到所有副本的消息最大 offset

Kafka 高并发优化

Producer 端优化

java
// 1. 批量发送
props.put("batch.size", 16384);      // 批量大小
props.put("linger.ms", 10);           // 等待时间

// 2. 压缩
props.put("compression.type", "snappy");  // LZ4 / Snappy / GZIP

// 3. 并发发送
List<Future<RecordMetadata>> futures = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
    futures.add(producer.send(new ProducerRecord<>("topic", value)));
}

Consumer 端优化

java
// 1. 提高并行度
consumer.subscribe(Arrays.asList("topic"));
// 分区数 = 最大 Consumer 并行度

// 2. 批量消费
while (true) {
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));

    List<Message> batch = new ArrayList<>();
    for (ConsumerRecord<String, String> record : records) {
        batch.add(parse(record));
    }
    processBatch(batch);  // 批量处理
}

总结

Kafka 核心知识点

知识点面试频率实战重要性
基本概念⭐⭐⭐⭐⭐⭐⭐⭐⭐
消息可靠性⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
消费者组⭐⭐⭐⭐⭐⭐⭐⭐
分区策略⭐⭐⭐⭐⭐⭐⭐
消息顺序⭐⭐⭐⭐⭐⭐⭐⭐
副本机制⭐⭐⭐⭐⭐⭐⭐

⚠️ 易错点提醒

  1. 同一 Consumer Group 内消息不重复消费
  2. 不同 Consumer Group 可以重复消费同一消息
  3. acks=all 配合 min.insync.replicas=2 保证高可靠
  4. 消息顺序只在同一 Partition 内保证
  5. 消费者需要手动提交位移才能保证 exactly-once