消息队列Kafka实践 | 青训营

48 阅读2分钟

消息队列kafka是一个分布式的、高吞吐量、高可扩展性的消息队列系统,它主要应用在日志收集、监控数据聚合、流式数据处理、在线和离线分析等场景中,是大数据生态中不可或缺的产品之一。kafka最初是由LinkedIn公司开发的,后来在2010年贡献给了Apache基金会,成为了一个开源项目,使用Scala语言编写。

kafka的核心概念有以下几个:

  • Producer(生产者):负责向kafka发送消息的客户端,可以指定消息的主题(Topic)和键值(Key)。
  • Consumer(消费者):负责从kafka接收消息的客户端,可以订阅一个或多个主题(Topic),并根据自己的处理能力拉取消息。
  • Topic(主题):kafka中的消息分类,每个主题可以有多个生产者和消费者,也可以有多个分区(Partition)。
  • Partition(分区):kafka中的消息存储单元,每个主题可以划分为一个或多个分区,每个分区是一个有序的消息序列,每条消息都有一个唯一的偏移量(Offset)。
  • Broker(节点):kafka中的服务器实例,多个Broker构成一个kafka集群,负责创建、存储、转发消息。
  • Replica(副本):kafka中的消息备份机制,每个分区都有一个或多个副本,其中一个作为Leader负责读写操作,其他的作为Follower负责同步数据和故障转移。
  • ZooKeeper(协调者):kafka中的集群管理组件,负责维护集群的元数据信息、状态信息、故障检测等功能。

要使用kafka进行消息传递,我们需要先创建一个或多个主题,并指定分区数和副本数。然后我们可以使用Producer API来向指定的主题发送消息,并使用Consumer API来从指定的主题接收消息。我们还可以使用Streams API来对消息进行流式处理,或者使用Connector API来与其他外部系统进行数据交互。

下面是一个使用Java语言编写的简单示例,演示了如何使用Producer API和Consumer API进行消息传递。假设我们已经在本地启动了一个单节点的kafka集群,并创建了一个名为test的主题。

// Producer示例
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.Properties;
public class ProducerDemo {
public static void main(String[] args) {
    // 创建生产者配置对象
    Properties props = new Properties();
    // 指定kafka集群地址
    props.put("bootstrap.servers", "localhost:9092");
    // 指定key和value的序列化器
    props.put("key.serializer", StringSerializer.class.getName());
    props.put("value.serializer", StringSerializer.class.getName());

    // 创建生产者对象
    KafkaProducer<String, String> producer = new KafkaProducer<>(props);

    // 创建消息记录对象
    ProducerRecord<String, String> record = new ProducerRecord<>("test", "hello", "world");

    // 发送消息
    producer.send(record);

    // 关闭生产者
    producer.close();
}
// Consumer示例 
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;
import java.time.Duration; 
import java.util.Collections; 
import java.util.Properties;
public class ConsumerDemo {
public static void main(String[] args) {
    // 创建消费者配置对象
    Properties props = new Properties();
    // 指定kafka集群地址
    props.put("bootstrap.servers", "localhost:9092");
    // 指定消费者组
    props.put("group.id", "test-group");
    // 指定key和value的反序列化器
    props.put("key.deserializer", StringDeserializer.class.getName());
    props.put("value.deserializer", StringDeserializer.class.getName());
    // 指定消费者的消费位置
    props.put("auto.offset.reset", "earliest");

    // 创建消费者对象
    KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);

    // 订阅主题
    consumer.subscribe(Collections.singleton("test"));

    // 循环拉取消息
    while (true) {
        // 拉取一批消息,参数为超时时间
        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
        // 遍历消息记录
        for (ConsumerRecord<String, String> record : records) {
            // 打印消息的主题、分区、偏移量、键值等信息
            System.out.println("topic: " + record.topic() + ", partition: " + record.partition() + ", offset: " + record.offset() + ", key: " + record.key() + ", value: " + record.value());
        }
    }
}