Kafka 消费者配置与监听器配置

96 阅读4分钟

如果需要精确控制消息处理后的偏移量,如下配置:

yaml

kafka:
  bootstrap-servers: com.kafka1:9092,com.kafka2:9092,com.kafka3:9092
  consumer:
    group-id: eorder-sync-consumer-group
    enable-auto-commit: false        # 关闭自动提交
    auto-commit-interval: 1000
    max-poll-records: 500
    key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
    value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
  listener:
    ack-mode: manual_immediate       # 此时手动确认才会真正生效
    concurrency: 12
    type: batch
    log-container-config: true
  • 偏移量提交行为

  • 1. 自动提交被禁用

    • enable-auto-commit: false 完全禁用了Kafka消费者的自动提交机制
    • 即使有 auto-commit-interval: 1000 配置,也不会生效
  • 2. 缺少确认模式配置

  • 由于没有配置 ack-mode,Spring Kafka会使用默认的确认模式
  • 默认ack-mode行为:
    • 对于 record 监听器(非batch):默认是 AckMode.BATCH
    • 对于 batch 监听器(配置了 type: batch):默认行为是在每批消息处理完成后自动提交偏移量

对比说明

配置提交行为
enable-auto-commit: trueKafka客户端自动提交,与消息处理无关
enable-auto-commit: false + 无ack-modeSpring容器批量处理完成后提交
enable-auto-commit: false + ack-mode: manual_immediate完全手动控制,需要代码中确认

Spring Kafka Listener Ack-Mode 详细解析

ack-mode 是 Spring Kafka 中控制消费者偏移量提交行为的重要配置,它决定了消息确认和偏移量提交的时机和方式。

1. ack-mode 的六种模式

1.1 RECORD(每记录确认)

yaml

listener:
  ack-mode: record

行为特点:

  • 每条消息处理成功后立即提交偏移量
  • 提交频率高,性能开销相对较大
  • 确保每条消息至少被处理一次
  • 如果处理失败,只有当前消息会重试

适用场景:

  • 消息处理重要性高,不能丢失
  • 消息处理时间较长,需要及时提交
  • 消息之间有独立性

1.2 BATCH(批量确认)- 默认模式

yaml

listener:
  ack-mode: batch

行为特点:

  • 每批消息全部处理成功后一次性提交偏移量
  • 提交频率低,性能较好
  • 如果批处理中某条消息失败,整批消息都会重试
  • 与 enable-auto-commit: false 配合使用

适用场景:

  • 批量处理消息的场景
  • 追求高性能的场景
  • 消息处理具有幂等性

1.3 TIME(时间间隔确认)

yaml

listener:
  ack-mode: time
  ack-time: 5000    # 5秒提交一次

行为特点:

  • 按照固定时间间隔提交偏移量
  • 与消息处理进度无关
  • 可能提交已处理但未确认的消息偏移量

适用场景:

  • 对实时性要求不高的场景
  • 消息处理时间不固定的场景

1.4 COUNT(计数确认)

yaml

listener:
  ack-mode: count
  ack-count: 100    # 每100条消息提交一次

行为特点:

  • 累积处理指定数量的消息后提交偏移量
  • 与时间无关,只与消息数量相关

适用场景:

  • 消息处理速率稳定的场景
  • 需要控制提交频率的场景

1.5 COUNT_TIME(计数或时间确认)

yaml

listener:
  ack-mode: count_time
  ack-time: 5000    # 5秒
  ack-count: 100    # 或100条消息

行为特点:

  • 满足计数或时间条件中的任意一个就提交
  • 先达到哪个条件就按哪个提交

适用场景:

  • 需要灵活控制提交策略的场景

1.6 MANUAL(手动确认)

yaml

listener:
  ack-mode: manual

行为特点:

  • 需要在代码中显式调用 acknowledge() 方法
  • 提供最精确的控制
  • 可以控制单条消息或整批消息的确认

代码示例:

java

@KafkaListener(topics = "myTopic")
public void listen(ConsumerRecord<String, String> record, 
                  Acknowledgment ack) {
    try {
        // 处理消息
        processMessage(record);
        // 手动确认
        ack.acknowledge();
    } catch (Exception e) {
        // 不确认,消息会重试
    }
}

1.7 MANUAL_IMMEDIATE(手动立即确认)

yaml

listener:
  ack-mode: manual_immediate

行为特点:

  • 与 MANUAL 类似,但确认后立即提交偏移量
  • 比 MANUAL 模式的响应更快

2. ack-mode 与相关配置的关系

2.1 与 enable-auto-commit 的关系

yaml

consumer:
  enable-auto-commit: false    # 必须为false,ack-mode才生效
listener:
  ack-mode: batch              # 此时ack-mode控制提交行为

2.2 与 type: batch 的关系

yaml

listener:
  ack-mode: batch
  type: batch                  # 批量监听模式
  • 在批量模式下,ack-mode 针对的是整批消息
  • 提交的是整批消息的最大偏移量

3. 不同 ack-mode 的提交时机对比

ack-mode提交时机性能可靠性使用复杂度
RECORD每条消息处理后较低最高简单
BATCH每批消息处理后简单
TIME固定时间间隔简单
COUNT固定数量后简单
COUNT_TIME计数或时间中等
MANUAL代码控制可调节最高复杂
MANUAL_IMMEDIATE代码控制立即提交可调节最高复杂

4. 实际应用建议

4.1 高可靠性场景

yaml

listener:
  ack-mode: record
  concurrency: 3    # 降低并发提高可靠性

4.2 高性能场景

yaml

listener:
  ack-mode: batch
  concurrency: 12
  type: batch

4.3 精确控制场景

yaml

listener:
  ack-mode: manual_immediate
  concurrency: 6

5. 注意事项

  1. 确保 enable-auto-commit: false,否则 ack-mode 不生效
  2. 合理设置 max-poll-records,避免批量过大导致内存问题
  3. 考虑消息幂等性,特别是在 BATCH 模式下
  4. 监控提交延迟,确保偏移量及时提交

通过合理配置 ack-mode,可以在性能、可靠性和复杂度之间找到最佳平衡点。