基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

Kafka生产者发送消息有哪些模式?

知识点图片

Kafka 生产者(Producer)发送消息主要有三种模式。这三种模式的区别在于生产者如何处理发送结果(响应),从而在吞吐量(性能)和可靠性(数据安全性)之间做出不同的权衡。

这三种模式分别是:

  1. 发后即忘(Fire-and-Forget)
  2. 同步发送(Synchronous Send)
  3. 异步发送(Asynchronous Send)

1. 发后即忘 (Fire-and-Forget)

生产者调用 send() 方法发送消息,但不关心消息是否成功到达。它不等待 Future 返回,也不注册回调函数。

  • 代码示例:
    java
    try {
        producer.send(record); // 直接发送,不处理返回值
    } catch (Exception e) {
        e.printStackTrace();
    }
  • 特点:
    • 吞吐量最高:不需要等待网络响应。
    • 可靠性最低:如果发送失败(例如 Broker 宕机、网络断开),生产者无法感知,会导致数据丢失
    • 注意:虽然 Kafka 自身有重试机制,但在这种模式下,如果重试多次依然失败,或者在发送出去之前就抛出异常(如序列化失败),数据就会丢失。
  • 适用场景:
    • 日志收集、用户点击流数据等允许少量数据丢失、但对性能要求极高的场景。

2. 同步发送 (Synchronous Send)

生产者调用 send() 方法发送消息,该方法返回一个 Future 对象,然后立即调用 Future.get() 等待结果。这会阻塞当前线程,直到 Kafka Broker 返回发送成功(ACK)或抛出异常。

  • 代码示例:
    java
    try {
        // send() 返回 Future,调用 get() 会阻塞直到收到响应
        RecordMetadata metadata = producer.send(record).get();
        System.out.println("发送成功: " + metadata.topic());
    } catch (Exception e) {
        e.printStackTrace(); // 处理发送失败的情况
    }
  • 特点:
    • 可靠性高:能够明确知道每条消息是否发送成功。如果失败,可以立即捕获异常进行处理。
    • 吞吐量低:因为是串行发送,必须等上一条发完才能发下一条,严重受限于网络往返时间(RTT)。
  • 适用场景:
    • 对数据可靠性要求极高,且数据量不大的场景。
    • 系统启动时的配置加载、关键的金融交易等不能容忍乱序或丢失的场景。

3. 异步发送 (Asynchronous Send)

生产者调用 send() 方法时,传入一个回调函数(Callback)send() 方法会立即返回,不会阻塞主线程。当 Kafka Broker 返回响应(成功或失败)时,Kafka 客户端会自动调用这个回调函数。

  • 代码示例:
    java
    producer.send(record, new Callback() {
        @Override
        public void onCompletion(RecordMetadata metadata, Exception exception) {
            if (exception == null) {
                // 发送成功
                System.out.println("发送成功: " + metadata.offset());
            } else {
                // 发送失败,进行处理(如记录日志、重试等)
                exception.printStackTrace();
            }
        }
    });
  • 特点:
    • 吞吐量高:支持高并发,生产者线程不需要等待响应,可以持续发送消息。Kafka 客户端会在后台进行批量发送(Batching)。
    • 可靠性较高:虽然不阻塞,但通过回调函数可以感知发送结果,如果失败可以在回调中处理。
    • 复杂性:需要在回调函数中处理异常逻辑。
  • 适用场景:
    • 绝大多数业务系统的默认选择。
    • 既需要高性能,又需要知道发送结果(以便进行错误记录或监控)的场景。

总结对比

模式 描述 优点 缺点 适用场景
发后即忘 只管发,不等待结果,不回调 性能最强,延迟最低 数据极易丢失,无法排查问题 日志、非关键埋点数据
同步发送 发送后阻塞等待结果 (Future.get) 可靠性最高,容易控制顺序 性能最差,吞吐量受限 关键配置、金融转账
异步发送 发送传入回调函数,不阻塞 性能好,兼顾了错误处理 代码逻辑稍复杂,可能出现乱序(若重试) 大多数业务开发

补充关键配置:acks

虽然上面是发送模式(API 调用方式),但消息的最终可靠性还取决于生产者的 acks 配置参数:

  • acks=0:生产者把消息发出去就认为成功,不等待 Broker 确认。这通常配合“发后即忘”模式使用,速度最快,丢数据风险最大。
  • acks=1 (默认):只要 Leader Broker 收到消息并写入本地日志,就返回成功。
  • acks=all (或 -1):Leader 必须等待所有 ISR(同步副本)都写入成功,才返回成功。这是最安全的配置。
00:00
00:00