kafka核心架构详解

目录

1.什么是kafka

2.什么是消息队列

3. 为什么使用消息队列

4.kafka的特点:

5.kafka的应用场景

6. kafka系统的架构基础(重点)

6.1 kafka系统架构中各组件的名称以及用途:

7. kafka中的命令行操作

8. kafkaJAVA中的API模拟生产者和消费者

8.1 一个正常的生产者和消费的的逻辑是:

8.2 生产者代码实现


1.什么是kafka

Kafka是一个分布式消息中间件,支持分区的、多副本的、多订阅者的、基于zookeeper协调的分布式消息系统。

通俗来说: kafka就是一个存储系统,存储的数据形式为“消息”;

它的主要作用类似于蓄水池,起到一个缓冲作用

2.什么是消息队列

常见的消息队列有activemq ,rabbitmq, rocketmq;

消息队列常用于两个系统之间数据传递

分布式消息传递基于可靠的消息队列,在客户端应用和消息系统之间异步传递消息。

有两种主要的消息传递模式:点对点传递模式、发布-订阅模式。

kafka采用的就是发布-订阅模式

3. 为什么使用消息队列

优点:异步,削峰,解耦

4.kafka的特点:

  1. 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, 由多个consumer group 对partition进行consume操作。
  2. 可扩展性:kafka集群支持热扩展
  3. 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
  4. 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)
  5. 高并发:支持数千个客户端同时读写

5.kafka的应用场景

主要用于数据处理系统中的缓冲!

6. kafka系统的架构基础(重点)

6.1 kafka系统架构中各组件的名称以及用途:

1) producer:消息生产者

消息生产者,就是向kafka broker 发消息的客户端。

2) consumer:消息消费者

consumer :消息消费者,从kafka broker 取消息的客户端。

consumer group:单个或多个consumer可以组成一个consumer group;这是 kafka 用来实现消息的广播(发给所有的 consumer)和单播(发给任意一个 consumer)的手段。一个 topic 可以有多个Consumer Group。

3 ) topic:数据的逻辑分类,可以理解为数据库中表的概念,topic又进一步分为patition , broker , offset

  1. partition: topic中数据的具体管理单元;(你可以理解为hbase中表的“region”概念)一个topic 可以划分为多个partition,分布到多个 broker上管理;每个partition由一个kafka broker服务器管理;partition 中的每条消息都会被分配一个递增的id(offset);每个 partition 是一个有序的队列,kafka 只保证按一个 partition 中的消息的顺序,不保证一个 topic 的整体(多个 partition 间)的顺序。每个partition都可以有多个副本;
  2. broker:一台kafka服务器就是一个broker.kafka集群就是由多个broker组成,一个broker可以有多个topic的多个partition;
  3. offset:消息在底层存储中的索引位置,kafka底层的存储文件就是以文件中第一条消息的offset来命名的,通过offset可以快速定位到消息的具体存储位置;             
  4. 小结:分区对于 kafka 集群的好处是:实现topic数据的负载均衡。分区对于消费者来说,可以提高并发度,提高效率

4) Leader:partition 副本中的一个角色,生产者和消费者只跟leader进行读写交互

partition replica中的一个角色,producer和consumer只跟leader交互(负责读写)。

5) 副本Replica:

partition的副本,保障partition的高可用(replica副本数目不能大于kafka broker节点的数目,否则报错。每个partition的所有副本中,必包括一个leader副本,其他的就是follower副本

6) follower

partition replica中的一个角色,从leader中拉取复制数据(只负责备份)。

如果leader所在节点宕机,follower中会选举出新的leader;

7) 偏移量Offset

每一条数据都有一个offset,是数据在该partition中的唯一标识(其实就是消息的索引号)。

各个consumer会保存其消费到的offset位置,这样下次可以从该offset位置开始继续消费;

consumer的消费offset保存在一个专门的topic(__consumer_offsets)中;(0.10.x版本以前是保存在zk中)

8)  消息Message

每一条massage是由一对key-value构成

组成massage format是由:

  1. Crc:主要用于校验消息的内容
  2. magic:主要用于标识 Kafka 版本。
  3. attribute:这里面存储了消息压缩使用的编码以及Timestamp类型
  4. key length:主要标识 Key的内容的长度
  5. key:占用 N个字节,存储的是 key 的具体内容;
  6. values length:主要标识 value 的内容的长度
  7. value:value即是消息的真实内容,在 Kafka 中这个也叫做payload

7. kafka中的命令行操作

1) 创建topic

./kafka-topics.sh --zookeeper linux01:2181,linux02:2181,linux03:2181 --create --replication-factor 3 --partitions 3 --topic tpc_1

参数解释:

--replication-factor  副本数量

--partitions 分区数量

--topic topic名称

2) 创建topic:手动指定副本的存储位置

bin/kafka-topics.sh --create --topic tpc_1  --zookeeper linux01:2181 --replica-assignment 0:1,1:2

会自动判断,要创建的topic的分区数及副本数以及每个副本所在的broker的位置

3) 查看当前系统中的所有topic

bin/kafka-topics.sh --zookeeper doitedu01:2181,doitedu02:2181,doitedu03:2181 --list

4) 删除topic

bin/kafka-topics.sh --zookeeper doitedu01:2181,doitedu02:2181,doitedu03:2181 --delete --topic test

删除topic,需要一个参数处于启用状态: delete.topic.enable = true

5) 查看某个topic的详情

 bin/kafka-topics.sh  --zookeeper linux01:2181linux02:2181 linux03:2181 --describe --topic tpc_1

Topic:tpc_1     PartitionCount:3        ReplicationFactor:3     Configs:
        Topic: tpc_1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1,0,2
        Topic: tpc_1    Partition: 1    Leader: 2       Replicas: 2,1,0 Isr: 2,1,0
        Topic: tpc_1    Partition: 2    Leader: 0       Replicas: 0,2,1 Isr: 0,2,1

结果解读:

从上面的结果中,可以看出,topic的分区数量,以及每个分区的副本数量,以及每个副本所在的broker节点,以及每个分区的leader副本所在broker节点,以及每个分区的ISR副本列表;

ISR: in  sync  replicas  同步副本

OSR:out  of  sync replicas 失去同步的副本(数据与leader之间的差距超过配置的阈值)

6)修改分区数

Kafka只支持增加分区,不支持减少分区

原因是:减少分区,代价太大(数据的转移,日志段拼接合并)

7) topic的动态参数更新

bin/kafka-configs.sh --zookeeper linux01:2181 --entity-type topics --entity-name tpc_1 --alter --add-config compression.type=gzip//添加动态参数命令

Topic:tpc_1     PartitionCount:3        ReplicationFactor:3     Configs:compression.type=gzip
        Topic: tpc_1    Partition: 0    Leader: 1       Replicas: 1,0,2 Isr: 1,0,2
        Topic: tpc_1    Partition: 1    Leader: 2       Replicas: 2,1,0 Isr: 2,1,0
        Topic: tpc_1    Partition: 2    Leader: 0       Replicas: 0,2,1 Isr: 0,2,1

bin/kafka-configs.sh --zookeeper linux01:2181 --entity-type topics --entity-name tpc_1 --alter --delete-config compression.type  //这个是删除参数命令

8) 命令行的producer打开producer

bin/kafka-console-producer.sh --broker-list linux01:9092 --topic tpc_1

9) 命令行consumer

bin/kafka-console-consumer.sh --bootstrap-server  linux01:9092  --from-beginning --topic tpc_1    //在命令行中消费消息

10) 指定要消费的分区,和要消费的其实offset

bin/kafka-console-consumer.sh --bootstrap-server linux01:9092,linux02:9092,linux03:9092 --topic tpc_1 --offset 2 --partition 0

8. kafkaJAVA中的API模拟生产者和消费者

8.1 一个正常的生产者和消费的的逻辑是:

一个正常的生产逻辑需要具备以下几个步骤

(1)配置生产者客户端参数及创建相应的生产者实例

(2)构建待发送的消息

(3)发送消息

(4)关闭生产者实例

8.2 生产者代码实现

package com.zxx.kafka.day01.demo;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;

import java.util.Properties;

/**
 * @Classname KafkaDemo2
 * @Date 2020/11/14 21:30
 * @Created by zxx
 * @Description
 */
public class KafkaDemo2 {
    public static void main(String[] args) {
        //设置配置文件
        Properties props = new Properties();
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"linux01:9092,linux02:9092,linux03:9092");
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
        props.put(ProducerConfig.ACKS_CONFIG,"all");
        // 涉及到一个重要的原理知识:kafka的幂等性
        props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG,"false");
        //创建一个生产者的实例对象
        KafkaProducer<String, String> producer = new KafkaProducer<>(props);
        for (int i = 0; i < 10000; i++) {
            ProducerRecord<String, String> tpc_2 = new ProducerRecord<>("tpc_2", "name" + i, RandomStringUtils.randomAscii(15));
            producer.send(tpc_2);
        }
        producer.close();


    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Apache Kafka 是一个分布式流处理平台,其架构设计旨在支持高吞吐量、持久化和可扩展的消息传递。Kafka核心架构由多个关键组件组成,这些组件协同工作以确保消息的高效传输与处理。 ### Kafka 架构详解 Kafka 的架构可以分为以下几个主要部分: 1. **主题(Topic)** Kafka 中的主题是消息的分类名称,每条消息都必须属于某个主题。主题被划分为多个分区(Partition),每个分区是一个有序、不可变的消息序列,并且能够持续追加[^4]。这种分区机制使得 Kafka 能够水平扩展以处理大量的数据流。 2. **生产者(Producer)** 生产者负责将消息发布到 Kafka 主题中。它们可以选择将消息发送到特定的分区,或者让 Kafka 自动决定分区策略。生产者可以通过配置来实现不同的语义,例如保证消息的顺序性或提高吞吐量。 3. **消费者(Consumer)** 消费者订阅一个或多个主题,并从 Kafka 集群中拉取数据进行处理。Kafka 提供了两种消费模式:点对点(Point-to-Point)和发布/订阅(Pub/Sub)。消费者通过维护偏移量(Offset)来跟踪已经消费的消息位置,从而保证消息处理的一致性和幂等性。 4. **消费者组(Consumer Group)** 消费者组是一组具有相同组 ID 的消费者实例。当多个消费者属于同一个组时,它们会共同分担主题中的分区,每个分区只能被组内的一个消费者消费。这种方式不仅提高了系统的并发处理能力,还简化了负载均衡和故障恢复的过程[^1]。 5. **服务代理(Broker)** Broker 是 Kafka 集群中的服务器节点,负责存储和转发消息。每个 Broker 可以管理多个主题的分区,并且可以通过复制机制来提高可用性和容错性。Kafka 使用 ZooKeeper 来协调集群内的元数据和服务发现,确保所有 Brokers 之间的状态一致性[^3]。 6. **ZooKeeper** Kafka 依赖于 ZooKeeper 进行集群管理和协调。ZooKeeper 存储了关于 Kafka 集群的各种元数据信息,如主题配置、分区分配和领导者选举等。它还用于监控 Brokers 和消费者的健康状况,并在发生故障时触发重新平衡操作[^3]。 7. **副本(Replica)** 为了保证数据的可靠性和容错性,Kafka 在多个 Broker 上维护了分区的副本。每个分区都有一个领导者副本(Leader Replica)和若干个跟随者副本(Follower Replicas)。只有领导者副本处理读写请求,而跟随者副本则异步地从领导者同步数据。如果领导者副本失效,系统会选择一个新的跟随者作为新的领导者继续提供服务。 8. **日志(Log)** Kafka 将消息持久化为磁盘上的日志文件,这不仅提供了高效的存储方式,还允许任意时间点的数据回溯。日志文件按照一定的规则滚动更新,并且可以根据保留策略自动清理旧数据,以节省存储空间。 9. **事务支持(Transaction Support)** Kafka 支持跨多个分区和主题的事务性操作,这意味着它可以确保一组消息要么全部成功提交,要么全部不提交。这一特性对于需要精确一次(Exactly Once)语义的应用非常重要,尤其是在复杂的业务逻辑中[^2]。 ### 工作原理概述 Kafka 的工作流程大致如下: - **消息产生**:生产者将消息发送到指定的主题。 - **消息存储**:Broker 接收到消息后,将其追加到相应的分区日志文件中。 - **消息消费**:消费者定期向 Broker 发起拉取请求,获取最新的消息并处理。 - **偏移量管理**:消费者处理完消息后,会提交当前的偏移量,以便下次可以从上次的位置继续消费。 - **故障恢复**:如果某个 Broker 或消费者失败,ZooKeeper 会检测到这种情况,并启动相应的恢复机制,比如重新分配分区或切换领导者副本。 Kafka 的这种架构设计使其非常适合用于大规模数据实时处理场景,如日志聚合、事件溯源、运营指标收集等。此外,它还能很好地与其他大数据工具集成,例如 Hadoop、Spark 等,进一步增强了其在现代数据管道中的地位[^1]。 ```java // 示例代码:创建一个简单的 Kafka 生产者 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); ProducerRecord<String, String> record = new ProducerRecord<>("my-topic", "key", "value"); try { RecordMetadata metadata = producer.send(record).get(); System.out.printf("Sent record to topic %s with offset %d%n", metadata.topic(), metadata.offset()); } catch (Exception e) { e.printStackTrace(); } finally { producer.close(); } ``` 上述 Java 示例展示了如何使用 Kafka 客户端 API 创建一个基本的生产者,并发送一条消息到指定的主题。这段代码演示了 Kafka 生产者的典型用法,包括设置必要的属性、构造生产记录以及发送消息的过程。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值