Kafka入门指南

Kafka是一个高性能的分布式流处理平台,用作消息中间件,提供消息持久化、高吞吐和可扩展性。其核心特性包括分区与副本机制,确保数据的可靠性和顺序性。在副本中,Leader处理读写,Follower与Leader同步,通过ISR和HW策略平衡性能与可靠性。生产者和消费者API示例展示了如何发送和接收消息。
摘要由CSDN通过智能技术生成

Kafka是什么

是一个分布式的流式处理平台,具有高吞吐,可持久化,可水平扩展,支持流式数据处理等多种特性。
主要功能
• 消息系统:作为消息中间件,提供系统解耦,冗余存储,流量削锋,缓冲,异步通信,扩展性,可恢复性等功能;还支持消息顺序性保障。
• 存储系统:把消息持久化到磁盘,可以配置数据长期保留
• 流式处理平台:提供一个完整的流式处理类库

体系结构

在这里插入图片描述

• Zookeeper:管理Kafka元数据
• Broker:Kafka服务节点,存储数据
• Producer:生产者
• Consumer:消费者

Broker组成

在这里插入图片描述

• Topic是一个逻辑概念,一个Topic中由多个分区(Partition)组成,横跨多个broker存储
• 一个Broker中有多个Topic
• Partition有多副本机制,一主多从,leader负责读写,follower只负责与leader进行数据同步
• 消息被顺序追加到分区日志文件尾部,有一个offset偏移量,是消息在分区中的唯一标识

Partition分区

分区有多副本机制,一个Leader和多个Follower

Leader

负责处理读写请求

Follower

只负责与Leader副本的消息同步,当Leader副本出现故障时,从follower副本中重新选举新的Leader对外提供服务

Offset

消息在分区中的唯一标识,偏移量,通过offset保证消息在分区的顺序性

AR、ISR、OSR

在这里插入图片描述

  • AR:分区中所有副本统称为AR
  • ISR:与 Leader 副本保持一定程度同步的副本,包括 Leader 副本
  • OSR:与 Leader 副本同步滞后的副本,不包括 Leader 副本

AR = ISR + OSR

正常情况下,所有的follower副本都应该与Leader副本保持一定的同步,即 AR = ISR

Leader 副本复制维护 ISR 集合中所有 Follower 副本的滞后状态
• 当 Follower 副本落后太多或失效,Leader 副本会把 Follower 副本从 ISR 集合中移到 OSR中
• 当 OSR 集合中有 Follower 追上了 Leader 副本,Leader 会把 Follower 从 OSR 集合中移到 ISR中

HW与LEO

HW:High Watermark高水位,标识了一个特定的消息偏移量,消费者只能拉取到这个offset之前的消息
LEO:Log End Offset,标识下一条待写消息的offset,等于日志中最后一条消息的offset值加1,分区ISR集合中每个副本都会维护自身的LEO。
在这里插入图片描述

如下图所示:
• Leader写入了5条消息,LEO为5
• Follower1同步了5条消息,LEO为5
• Follower2同步了4条消息,LEO为4
那么这个分区的 HW 取最小值4,消费者可以消费到 offset 为 0 至 3 之间的消息。
在这里插入图片描述

总结:Kafka的复制机制既不是完全的同步复制,也不是单纯的异步复制。而是基于ISR和高水位的方式,有效的权衡了数据的可靠性和性能之间的关系。

生产消费示例代码

生产者

public static void main(String[] args) throws InterruptedException {
    // 创建 producer
    KafkaProducer<String, String> producer = createProducer();
    // 消息记录
    ProducerRecord<String, String> record = new ProducerRecord<String, String>("hello-kafka",
                                                                               "Message", "hello kafka message:" + Math.random());
    producer.send(record, new Callback() {
        public void onCompletion(RecordMetadata metadata, Exception exception) {
            System.out.println(metadata.toString());
            if (exception == null) {
                System.out.println("消息发送成功");
            } else {
                System.out.println("消息发送异常");
                exception.printStackTrace();
            }
        }
    });
    Thread.sleep(5000);
    producer.close();
}
public static KafkaProducer<String, String> createProducer() {
    Properties properties = new Properties();
    properties.put("bootstrap.servers", "localhost:9092");
    properties.put("acks", "all");
    properties.put("retries", 1);
    properties.put("batch.size", 16384);
    properties.put("key.serializer", StringSerializer.class.getName());
    properties.put("value.serializer", StringSerializer.class.getName());
    properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG, DemoPartitioner.class);
    properties.put(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, DemoInterceptor.class.getName());
    return new KafkaProducer<String, String>(properties);
}

消费者

public static void main(String[] args) throws InterruptedException {
    // 创建消费者
    KafkaConsumer<String, String> consumer = createConsumer();
    // 订阅topic
    consumer.subscribe(Collections.singletonList("hello-kafka"));
    while (true) {
        ConsumerRecords<String, String> msgList = consumer.poll(2000);
        if (msgList != null && msgList.count() > 0) {
            for (ConsumerRecord<String, String> msg : msgList) {
                System.out.println("接收到消息key:" + msg.key());
                System.out.println("接收到消息value:" + msg.value());
                System.out.println("接收到消息offset:" + msg.offset());
            }
        }
        System.out.println("===================================");
        Thread.sleep(10000);
    }
}
public static KafkaConsumer<String, String> createConsumer() {
    Properties properties = new Properties();
    properties.put("bootstrap.servers", "localhost:9092");
    properties.put("group.id", "groupA");
    properties.put("enable.auto.commit", "true");
    properties.put("auto.commit.interval.ms", "1000");
    properties.put("auto.offset.reset", "earliest");
    properties.put("session.timeout.ms", "30000");
    properties.put("key.deserializer", StringDeserializer.class.getName());
    properties.put("value.deserializer", StringDeserializer.class.getName());
    return new KafkaConsumer<String, String>(properties);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值