大厂面试真题-说说Kafka消息的不重复和不丢失

说说kafka不重不丢?

Kafka 致力于实现不重不丢,这意味着它努力确保消息不会被重复传递,也不会在传递过程中丢失。为
了实现这一目标,Kafka 采用了以下关键机制:

  1. 消息复制和副本:Kafka 使用多个副本来保存消息,每个分区的消息都有多个副本分布在不同的服
    务器上。这样,即使某个服务器故障,仍然可以从其他副本中获取消息。

  2. 消费者位移:Kafka 记录了每个消费者在每个分区中的位移(offset),表示消费者已经处理到哪
    个位置的消息。消费者可以定期提交位移,以确保它们不会重复消费消息。

  3. 生产者确认机制:Kafka 生产者在将消息发送到服务器后,会等待服务器的确认
    (acknowledgment)。只有当服务器确认接收到消息后,生产者才会认为消息已经成功发送。

  4. 事务支持:Kafka 提供了事务支持,允许生产者在发送消息时执行事务性操作。这意味着消息要么
    全部成功发送,要么一个都不发送,以确保不重不丢。

  5. 幂等性生产者:Kafka 生产者支持幂等性,即使生产者发送相同的消息多次,只有一次会生效,有
    助于避免重复消息。
    以下是一个简单的 Java 代码示例,实现了 Kafka 生产者和消费者功能,同时展示了如何确保消息不重
    复和不丢失。
    生产者端(Producer.java):

    import org.apache.kafka.clients.producer.KafkaProducer;
    import org.apache.kafka.clients.producer.Producer;
    import org.apache.kafka.clients.producer.ProducerRecord;
    import org.apache.kafka.common.serialization.StringSerializer;
    import java.time.Duration;
    import java.util.Properties;
    public class Producer {
    public static void main(String[] args) {
    // 配置生产者参数
    Properties props = new Properties();
    props.put("bootstrap.servers", "localhost:9092");
    props.put("key.serializer",
    "org.apache.kafka.common.serialization.StringSerializer");
    props.put("value.serializer",
    "org.apache.kafka.common.serialization.StringSerializer");
    // 创建生产者实例
    Producer<String, String> producer = new KafkaProducer<>(props);
    // 发送消息
    for (int i = 0; i < 10; i++) {
    String message = "Hello, Kafka!" + i;
    producer.send(new ProducerRecord<>("test-topic", message));
    System.out.printf("Sent message: %s%n", message);
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    import org.apache.kafka.clients.producer.KafkaProducer;
    import org.apache.kafka.clients.producer.Producer;
    import org.apache.kafka.clients.producer.ProducerRecord;
    import org.apache.kafka.common.serialization.StringSerializer;
    import java.time.Duration;
    import java.util.Properties;
    public class Producer {
    public static void main(String[] args) {
    // 配置生产者参数
    Properties props = new Properties();
    props.put("bootstrap.servers", "localhost:9092");
    props.put("key.serializer",
    "org.apache.kafka.common.serialization.StringSerializer");
    props.put("value.serializer",
    "org.apache.kafka.common.serialization.StringSerializer");
    // 创建生产者实例
    Producer<String, String> producer = new KafkaProducer<>(props);
    // 发送消息
    for (int i = 0; i < 10; i++) {
    String message = "Hello, Kafka!" + i;
    producer.send(new ProducerRecord<>("test-topic", message));
    System.out.printf("Sent message: %s%n", message);
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }

这个生产者实例使用了 KafkaProducer 类,并发送了 10 条消息到名为 test-topic 的 topic。在 main
方法中,调用 send 方法发送消息,并在发送消息后打印消息内容。生产者在运行过程中,会持续发送
消息。当需要结束程序时,调用 close 方法关闭生产者。
消费者端(Consumer.java):

java 复制代码
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.common.serialization.StringSerializer;
import java.time.Duration;
import java.util.Collections;
import java.util.Properties;
public class Consumer {
public static void main(String[] args) {
// 配置消费者参数
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer",
"org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer",
"org.apache.kafka.common.serialization.StringSerializer");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
// 创建消费者实例
Consumer<String, String> consumer = new KafkaConsumer<>(props);
// 订阅 topic
consumer.subscribe(Collections.singletonList("test-topic"));
// 消费消息
while (true) {
ConsumerRecords<String, String> records =
consumer.poll(Duration.ofMillis(1000));
for (ConsumerRecord<String, String> record : records) {
System.out.printf("offset = %d, key = %s, value = %s%n",
record.offset(), record.key(), record.value());
}
}
// 关闭消费者
consumer.close();
}
}

这个消费者实例使用了 KafkaConsumer 类,并订阅了名为 test-topic 的 topic。在 main 方法中,使用
poll 方法轮询消息,并在接收到消息时打印 offset、key 和 value。消费者在运行过程中,会持续接收
和处理消息。当需要结束程序时,调用 close 方法关闭消费者。

相关推荐
吴声子夜歌2 分钟前
ApacheCommons——commons-text(模板替换与文本算法)
java·开发语言·算法·apache
Haooog15 分钟前
Agent 开发中的 Memory:State、短期记忆、长期记忆与 Memory Retrieval
java·agent·memory
砚底藏山河22 分钟前
【量化纯GET实战 #23】多股票相关性:用收益率看板块联动
java·数据库·python·金融·数据分析
抠脚小弟37 分钟前
Spring Cache 使用详解:从入门到实战
java·spring
ZGG0031 小时前
MySQL 索引详解:B+ 树、聚簇索引与最左前缀
java·数据库·mysql
萧瑟余晖1 小时前
Java深入解析篇五十四之对象模型详解
java·开发语言
张文是假的啊1 小时前
Java | record | Controller逻辑
java·开发语言
勿忘,瞬间1 小时前
Mybatis高阶
java·数据库·mybatis
嘻哈baby3 小时前
Go 函数中的参数为什么不支持默认值?
java·开发语言·jvm
慧都小项3 小时前
MyEclipse 2026:当 Agent、MCP 与 Java 26 进入 Eclipse 工作流
java·eclipse·springboot·copilot·myeclipse