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();


    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值