目录
1.什么是kafka
Kafka是一个分布式消息中间件,支持分区的、多副本的、多订阅者的、基于zookeeper协调的分布式消息系统。
通俗来说: kafka就是一个存储系统,存储的数据形式为“消息”;
它的主要作用类似于蓄水池,起到一个缓冲作用;
2.什么是消息队列
常见的消息队列有activemq ,rabbitmq, rocketmq;
消息队列常用于两个系统之间的数据传递;
分布式消息传递基于可靠的消息队列,在客户端应用和消息系统之间异步传递消息。
有两种主要的消息传递模式:点对点传递模式、发布-订阅模式。
kafka采用的就是发布-订阅模式
3. 为什么使用消息队列
优点:异步,削峰,解耦
4.kafka的特点:
- 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, 由多个consumer group 对partition进行consume操作。
- 可扩展性:kafka集群支持热扩展
- 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
- 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)
- 高并发:支持数千个客户端同时读写
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
- partition: topic中数据的具体管理单元;(你可以理解为hbase中表的“region”概念)一个topic 可以划分为多个partition,分布到多个 broker上管理;每个partition由一个kafka broker服务器管理;partition 中的每条消息都会被分配一个递增的id(offset);每个 partition 是一个有序的队列,kafka 只保证按一个 partition 中的消息的顺序,不保证一个 topic 的整体(多个 partition 间)的顺序。每个partition都可以有多个副本;
- broker:一台kafka服务器就是一个broker.kafka集群就是由多个broker组成,一个broker可以有多个topic的多个partition;
- offset:消息在底层存储中的索引位置,kafka底层的存储文件就是以文件中第一条消息的offset来命名的,通过offset可以快速定位到消息的具体存储位置;
- 小结:分区对于 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是由:
- Crc:主要用于校验消息的内容
- magic:主要用于标识 Kafka 版本。
- attribute:这里面存储了消息压缩使用的编码以及Timestamp类型
- key length:主要标识 Key的内容的长度
- key:占用 N个字节,存储的是 key 的具体内容;
- values length:主要标识 value 的内容的长度
- 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,1bin/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(); } }