大数据技术之Kafka

一 .概述

1.定义

在这里插入图片描述
在这里插入图片描述

1.2 消息队列

目 前企 业中比 较常 见的 消息 队列产 品主 要有 Kafka、ActiveMQ 、RabbitMQ 、
RocketMQ 等。
在大数据场景主要采用 Kafka 作为消息队列。在 JavaEE 开发中主要采用 ActiveMQ、
RabbitMQ、RocketMQ。可以关注尚硅谷教育公众号回复 java,免费获取相关资料。
传统的消息队列的主要应用场景包括:缓存/消峰、解耦和异步通信。

1.2.1 消息队列的两种模式

在这里插入图片描述

点对点:一个生产者,一个消费者,一个topic ,会删除数据
发布订阅:多个生产者,多个消费者。而且相互独立,多个topic,不会删除数据。

二.架构

1)生产者
海量数据
2)broker
(1)broker 服务器
(2)topic 主题 对数据分类
(3)分区
(4)可靠性—副本
(5)leader followe
(6)生产者和消费者 只针对leader
3)消费者
(1)消费者和生产者相互独立
(2)消费者组(某个分区分区只能由一个消费者消费)
4)zookeeper
(1)存储broker.ids
(2)leader
在这里插入图片描述
(1)Producer:消息生产者,就是向 Kafka broker 发消息的客户端。
(2)Consumer:消息消费者,向 Kafka broker 取消息的客户端。
(3)Consumer Group(CG):消费者组,由多个 consumer 组成。消费者组内每个消
费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费;消费者组之间互不
影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。
(4)Broker:一台 Kafka 服务器就是一个 broker。一个集群由多个 broker 组成。一个
broker 可以容纳多个 topic。
(5)Topic:可以理解为一个队列,生产者和消费者面向的都是一个 topic。
(6)Partition:为了实现扩展性,一个非常大的 topic 可以分布到多个 broker(即服
务器)上,一个 topic 可以分为多个 partition,每个 partition 是一个有序的队列。
(7)Replica:副本。一个 topic 的每个分区都有若干个副本,一个 Leader 和若干个
Follower。
(8)Leader:每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数
据的对象都是 Leader。
(9)Follower:每个分区多个副本中的“从”,实时从 Leader 中同步数据,保持和
Leader 数据的同步。Leader 发生故障时,某个 Follower 会成为新的 Leader。

三.Kafka 快速入门

3.1 安装部署
注意:(1)broker.id 必须全局唯一
(2)启动停止 先停止kafaka 再停zk

3.1.1 集群规划
在这里插入图片描述

3.1.2 集群部署
0)官方下载地址:

http://kafka.apache.org/downloads.html

1)解压安装包(注意目录)

[atguigu@hadoop102 software]$ tar -zxvf kafka_2.12-3.0.0.tgz -C 
/opt/module/

2)修改解压后的文件名称

[atguigu@hadoop102 module]$ mv kafka_2.12-3.0.0/ kafka

3)进入到/opt/module/kafka 目录,修改配置文件

[atguigu@hadoop102 kafka]$ cd config/
[atguigu@hadoop102 config]$ vim server.properties

输入以下内容:(对比需要修改的地方,特别注意id)

#broker 的全局唯一编号,不能重复,只能是数字。
broker.id=0
#处理网络请求的线程数量
num.network.threads=3
#用来处理磁盘 IO 的线程数量
num.io.threads=8
#发送套接字的缓冲区大小
socket.send.buffer.bytes=102400
#接收套接字的缓冲区大小
socket.receive.buffer.bytes=102400
#请求套接字的缓冲区大小
socket.request.max.bytes=104857600
#kafka 运行日志(数据)存放的路径,路径不需要提前创建,kafka 自动帮你创建,可以
配置多个磁盘路径,路径与路径之间可以用","分隔
log.dirs=/opt/module/kafka/datas
#topic 在当前 broker 上的分区个数
num.partitions=1
#用来恢复和清理 data 下数据的线程数量
num.recovery.threads.per.data.dir=1
#每个 topic 创建时的副本数,默认时 1 个副本
offsets.topic.replication.factor=1
#segment 文件保留的最长时间,超时将被删除
log.retention.hours=168
#每个 segment 文件的大小,默认最大 1G
log.segment.bytes=1073741824
#检查过期数据的时间,默认 5 分钟检查一次是否数据过期
log.retention.check.interval.ms=300000
#配置连接 Zookeeper 集群地址(在 zk 根目录下创建/kafka,方便管理)
zookeeper.connect=hadoop102:2181,hadoop103:2181,hadoop104:2181

检查需要更改的地方
4)分发安装包

[atguigu@hadoop102 module]$ xsync kafka/

5)分别在 hadoop103 和 hadoop104 上修改配置文件/opt/module/kafka/config/server.properties
中的 broker.id=1、broker.id=2
注:broker.id 不得重复,整个集群中唯一。

[atguigu@hadoop103 module]$ vim kafka/config/server.properties
修改:
#The id of the broker. This must be set to a unique integer for 
each broker.
broker.id=1
[atguigu@hadoop104 module]$ vim kafka/config/server.properties
修改:
#The id of the broker. This must be set to a unique integer for 
each broker.
broker.id=2

6)配置环境变量
(1)在/etc/profile.d/my_env.sh 文件中增加 kafka 环境变量配置

[atguigu@hadoop102 module]$ sudo vim /etc/profile.d/my_env.sh

增加如下内容:

#KAFKA_HOME
export KAFKA_HOME=/opt/module/kafka
export PATH=$PATH:$KAFKA_HOME/bin

(2)刷新一下环境变量。

[atguigu@hadoop102 module]$ source /etc/profile

(3)分发环境变量文件到其他节点,并 source。

[atguigu@hadoop102 module]$ sudo /home/atguigu/bin/xsync 
/etc/profile.d/my_env.sh
[atguigu@hadoop103 module]$ source /etc/profile
[atguigu@hadoop104 module]$ source /etc/profile

7)启动集群

1)先启动 Zookeeper 集群,然后启动 Kafka[atguigu@hadoop102 kafka]$ zk.sh start 
2)依次在 hadoop102、hadoop103、hadoop104 节点上启动 Kafka[atguigu@hadoop102 kafka]$ bin/kafka-server-start.sh -daemon
config/server.properties
[atguigu@hadoop103 kafka]$ bin/kafka-server-start.sh -daemon
config/server.properties
[atguigu@hadoop104 kafka]$ bin/kafka-server-start.sh -daemon
config/server.properties

8)关闭集群

[atguigu@hadoop102 kafka]$ bin/kafka-server-stop.sh 
[atguigu@hadoop103 kafka]$ bin/kafka-server-stop.sh 
[atguigu@hadoop104 kafka]$ bin/kafka-server-stop.sh

9)集群启停脚本
(1)在/home/atguigu/bin 目录下创建文件 kf.sh 脚本文件

[atguigu@hadoop102 bin]$ vim kf.sh

脚本如下:

#! /bin/bash
case $1 in
"start"){
 for i in hadoop102 hadoop103 hadoop104
 do
 echo " --------启动 $i Kafka-------"
 ssh $i "/opt/module/kafka/bin/kafka-server-start.sh -
daemon /opt/module/kafka/config/server.properties"
 done
};;
"stop"){
 for i in hadoop102 hadoop103 hadoop104
 do
 echo " --------停止 $i Kafka-------"
 ssh $i "/opt/module/kafka/bin/kafka-server-stop.sh "
 done
};;
esac

(2)添加执行权限

[atguigu@hadoop102 bin]$ chmod +x kf.sh

(3)启动集群命令

[atguigu@hadoop102 ~]$ kf.sh start

(4)停止集群命令

[atguigu@hadoop102 ~]$ kf.sh stop

注意:停止 Kafka 集群时,一定要等 Kafka 所有节点进程全部停止后再停止 Zookeeper
集群。因为 Zookeeper 集群当中记录着 Kafka 集群相关信息,Zookeeper 集群一旦先停止,
Kafka 集群就没有办法再获取停止进程的信息,只能手动杀死 Kafka 进程了。

四 . Kafka 命令行操作

4.1 主题命令行操作

1)查看操作主题命令参数

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh

在这里插入图片描述

2)查看当前服务器中的所有 topic

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server 
hadoop102:9092 --list

3)创建 first topic

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server 
hadoop102:9092 --create --partitions 1 --replication-factor 3 --
topic first
选项说明:
--topic 定义 topic 名
--replication-factor 定义副本数
--partitions 定义分区数

4)查看 first 主题的详情

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server 
hadoop102:9092 --describe --topic first

5)修改分区数(注意:分区数只能增加,不能减少)

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server 
hadoop102:9092 --alter --topic first --partitions 3

6)再次查看 first 主题的详情

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server 
hadoop102:9092 --describe --topic first

7)删除 topic(一般不用)

[atguigu@hadoop102 kafka]$ bin/kafka-topics.sh --bootstrap-server 
hadoop102:9092 --delete --topic first

4.2 生产者命令行操作1)

1)查看操作生产者命令参数

[atguigu@hadoop102 kafka]$ bin/kafka-console-producer.sh

在这里插入图片描述
2)发送消息

[atguigu@hadoop102 kafka]$ bin/kafka-console-producer.sh --
bootstrap-server hadoop102:9092 --topic first
>hello world
>atguigu atguigu

4.3 消费者命令行操作

1)查看操作消费者命令参数

[atguigu@hadoop102 kafka]$ bin/kafka-console-consumer.sh

在这里插入图片描述
在这里插入图片描述
2)消费消息
(1)消费 first 主题中的数据。

[atguigu@hadoop102 kafka]$ bin/kafka-console-consumer.sh --
bootstrap-server hadoop102:9092 --topic first

(2)把主题中所有的数据都读取出来(包括历史数据)。

[atguigu@hadoop103 kafka]$ bin/kafka-console-consumer.sh --
bootstrap-server hadoop102:9092 --from-beginning --topic first

五 .Kafka 生产者

5.1 发送原理

在消息发送的过程中,涉及到了两个线程——main 线程和 Sender 线程。在 main 线程
中创建了一个双端队列 RecordAccumulator。main 线程将消息发送给 RecordAccumulator,
Sender 线程不断从 RecordAccumulator 中拉取消息发送到 Kafka Broker。
在这里插入图片描述
发送流程(生产者发送数据到集群)
主线程调用send()方法,再经过拦截器。数据在经过序列化,
再走到分区器(RecordAccumulator,其实是一个双端队列)。这一块都是在内存中完成的,默认为32M.每一个
批次的默认为16k。
sender线程:主动拉取数据。每批次的数据满了过后再拉取。或者linger。ms
达到0ms。以节点(broke)为key.最多5个请求没有应答的时候可以发送
数据。
selector负责打开链路,类似与输入输出流
集群收到后回进行一个副本同步,同步后开始应答。应答成功后清理分区的数据。

5.2 生产者重要参数列表

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

5.3 异步发送 API

1)需求:创建 Kafka 生产者,采用异步的方式发送到 Kafka Broker
2)代码编写
(1)创建工程 kafka
(2)导入依赖

<dependencies>
 <dependency>
 <groupId>org.apache.kafka</groupId>
 <artifactId>kafka-clients</artifactId>
 <version>3.0.0</version>
 </dependency>
</dependencies>

(3)创建包名:com.atguigu.kafka.producer
(4)编写不带回调函数的 API 代码

package com.atguigu.kafka.producer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import java.util.Properties;
public class CustomProducer {
 public static void main(String[] args) throws 
InterruptedException {
 // 1. 创建 kafka 生产者的配置对象
 Properties properties = new Properties();
 // 2. 给 kafka 配置对象添加配置信息:bootstrap.servers
 properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, 
"hadoop102:9092");
 
 // key,value 序列化(必须):key.serializer,value.serializer
 properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, 
"org.apache.kafka.common.serialization.StringSerializer");
 
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, 
"org.apache.kafka.common.serialization.StringSerializer");
 // 3. 创建 kafka 生产者对象
 KafkaProducer<String, String> kafkaProducer = new 
KafkaProducer<String, String>(properties);
 // 4. 调用 send 方法,发送消息
 for (int i = 0; i < 5; i++) {
 kafkaProducer.send(new 
ProducerRecord<>("first","atguigu " + i));
 }
 // 5. 关闭资源
 kafkaProducer.close();
 }
}

测试:
①在 hadoop103 上开启 Kafka 消费者。

[atguigu@hadoop103 kafka]$ bin/kafka-console-consumer.sh --
bootstrap-server hadoop102:9092 --topic first

②在 IDEA 中执行代码,观察 hadoop102 控制台中是否接收到消息。

[atguigu@hadoop103 kafka]$ bin/kafka-console-consumer.sh --
bootstrap-server hadoop103:9092 --topic first

接收到的信息为:

atguigu 0
atguigu 1
atguigu 2
atguigu 3
atguigu 4

总结步骤
0)配置
(1)连接
(2)key value序列化
1)创建生产者
2)发送数据
send()
带回调:send(,new Callback)
同步发送: send(),send(,new Callback.get())(其他一样)
3)关闭资源

5.4 生产者分区

1)分区好处:
存储计算在这里插入图片描述
2)默认分区原则
(1)指定分区,按分区走
(2)指定了key,按key的hashcode值%分区数
(3)什么都没有指定,则通过粘性规则,(一个一个用完位置,随机)
3)自定义分区
定义类,实现partition接口
下面来个列子:
1)需求
例如我们实现一个分区器实现,发送过来的数据中如果包含 atguigu,就发往 0 号分区,
不包含 atguigu,就发往 1 号分区。
2)实现步骤
(1)定义类实现 Partitioner 接口。
(2)重写 partition()方法。

package com.atguigu.kafka.producer;
import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;
import java.util.Map;
/**
* 1. 实现接口 Partitioner
* 2. 实现 3 个方法:partition,close,configure
* 3. 编写 partition 方法,返回分区号
*/
public class MyPartitioner implements Partitioner {
 /*
 * 返回信息对应的分区
 * @param topic 主题
 * @param key 消息的 key
 * @param keyBytes 消息的 key 序列化后的字节数组
 * @param value 消息的 value
 * @param valueBytes 消息的 value 序列化后的字节数组
 * @param cluster 集群元数据可以查看分区信息
 * @return
 */
 @Override
 public int partition(String topic, Object key, byte[] 
keyBytes, Object value, byte[] valueBytes, Cluster cluster) {
 // 获取消息
 String msgValue = value.toString();
 // 创建 partition
 int partition;
 // 判断消息是否包含 atguigu
 if (msgValue.contains("atguigu")){
 partition = 0;
 }else {
 partition = 1;
 }
 // 返回分区号
 return partition;
 }
 // 关闭资源
 @Override
 public void close() {
 }
 // 配置方法
 @Override
 public void configure(Map<String, ?> configs) {
 }
}

(3)使用分区器的方法,在生产者的配置中添加分区器参数。

package com.atguigu.kafka.producer;
import org.apache.kafka.clients.producer.*;
import java.util.Properties;
public class CustomProducerCallbackPartitions {
 public static void main(String[] args) throws 
InterruptedException {

Properties properties = new Properties();
 
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop102:9092");

 properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, 
StringSerializer.class.getName());
 
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, 
StringSerializer.class.getName());

 // 添加自定义分区器
properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,"com.atgui
gu.kafka.producer.MyPartitioner");

 KafkaProducer<String, String> kafkaProducer = new KafkaProducer<>(properties);
 
 for (int i = 0; i < 5; i++) {
 kafkaProducer.send(new ProducerRecord<>("first", 
"atguigu " + i), new Callback() {
 @Override
 public void onCompletion(RecordMetadata metadata, 
Exception e) {
 if (e == null){
 System.out.println(" 主题: " + 
metadata.topic() + "->" + "分区:" + metadata.partition()
 );
 }else {
 e.printStackTrace();
 }
 }
 });
 }
 kafkaProducer.close();
 }
}

这里是使用的带回调的异步发送。
(4)测试
①在 hadoop103 上开启 Kafka 消费者。

[atguigu@hadoop103 kafka]$ bin/kafka-console-consumer.sh --
bootstrap-server hadoop102:9092 --topic first

②在 IDEA 控制台观察回调信息。

主题:first->分区:0
主题:first->分区:0
主题:first->分区:0
主题:first->分区:0
主题:first->分区:0

5.5 生产经验——生产者如何提高吞吐量

1.批次大小,默认每次发送16k,可以调整为32k
2.linger.ms:等待时间(等待时间如果为0ms,则无延迟发送,不会等待分区满了再发送) 修改为5-100ms(但是会带来数据的延迟)
3.压缩
4.缓冲区大小,默认32m,可修改为64m

在这里插入图片描述

5.6 生产经验——数据可靠性

acks应答级别
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
0 :会出现丢失数据
1:也可能会丢失。多用于传输普通日志
-1:完全可靠,条件(分区副本大于等于2 ,isr 的副本数大于等于2),但是可能出现数据重复(leader挂了的情况)
数据重复我们可以使用幂等性和事务。
幂等性原理:
在这里插入图片描述

幂等性默认打开。

事务
(1)底层基于幂等性
在这里插入图片描述
(2)Kafka 的事务一共有如下 5 个 API

// 1 初始化事务
void initTransactions();
// 2 开启事务
void beginTransaction() throws ProducerFencedException;
// 3 在事务内提交已经消费的偏移量(主要用于消费者)
void sendOffsetsToTransaction(Map<TopicPartition, OffsetAndMetadata> offsets,
 String consumerGroupId) throws 
ProducerFencedException;
// 4 提交事务
void commitTransaction() throws ProducerFencedException;
// 5 放弃事务(类似于回滚事务的操作)
void abortTransaction() throws ProducerFencedException;

(3)单个 Producer,使用事务保证消息的仅一次发送

package com.atguigu.kafka.producer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import java.util.Properties;
public class CustomProducerTransactions {
 public static void main(String[] args) throws 
InterruptedException {
 // 1. 创建 kafka 生产者的配置对象
 Properties properties = new Properties();
 // 2. 给 kafka 配置对象添加配置信息
 properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, 
"hadoop102:9092");
 // key,value 序列化
 properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, 
StringSerializer.class.getName());
 
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, 
StringSerializer.class.getName());
 // 设置事务 id(必须),事务 id 任意起名
 properties.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG, 
"transaction_id_0");
 // 3. 创建 kafka 生产者对象
 KafkaProducer<String, String> kafkaProducer = new 
KafkaProducer<String, String>(properties);
 // 初始化事务
 kafkaProducer.initTransactions();
 // 开启事务
 kafkaProducer.beginTransaction();
 try {
 // 4. 调用 send 方法,发送消息
 for (int i = 0; i < 5; i++) {
 // 发送消息
 kafkaProducer.send(new ProducerRecord<>("first", 
"atguigu " + i));
 }
// int i = 1 / 0;
 // 提交事务
 kafkaProducer.commitTransaction();
 } catch (Exception e) {
 // 终止事务
 kafkaProducer.abortTransaction();
 } finally {
 // 5. 关闭资源
 kafkaProducer.close();
 }
 }
}

5.7 生产经验——数据有序

在这里插入图片描述

5.8 生产经验——数据乱序

在这里插入图片描述
#

六 Kafka Broker

6.1 Zookeeper 存储的 Kafka 信息

在这里插入图片描述

6.2 Kafka Broker 总体工作流程

在这里插入图片描述

(2) Broker 重要参数
在这里插入图片描述
在这里插入图片描述

6.3 生产经验——节点服役和退役

1)新节点准备
(1)关闭 hadoop104,并右键执行克隆操作。(这里是为了方便,直接从hadoop104开始复制,正规操作应该用hadoop100模板机进行复制)
(2)开启 hadoop105,并修改 IP 地址。

root@hadoop105 ~]# vim /etc/sysconfig/network-scripts/ifcfgens33
DEVICE=ens33
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=static
NAME="ens33"
IPADDR=192.168.10.105
PREFIX=24
GATEWAY=192.168.10.2
DNS1=192.168.10.2

(3)在 hadoop105 上,修改主机名称为 hadoop105。

[root@hadoop105 ~]# vim /etc/hostname
hadoop105

(4)重新启动 hadoop104、hadoop105。
(5)修改 haodoop105 中 kafka 的 broker.id 为 3。
(6)删除 hadoop105 中 kafka 下的 datas 和 logs。
[atguigu@hadoop105 kafka]$ rm -rf datas/* logs/*
(7)启动 hadoop102、hadoop103、hadoop104 上的 kafka 集群。

[atguigu@hadoop102 ~]$ zk.sh start
[atguigu@hadoop102 ~]$ kf.sh start

(8)单独启动 hadoop105 中的 kafka。

[atguigu@hadoop105 kafka]$ bin/kafka-server-start.sh -
daemon ./config/server.properties

2)执行负载均衡操作
(1)创建一个要均衡的主题。

[atguigu@hadoop102 kafka]$ vim topics-to-move.json
{
 "topics": [
 {"topic": "first"}
 ],
 "version": 1
}

(2)生成一个负载均衡的计划。

[atguigu@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh --
bootstrap-server hadoop102:9092 --topics-to-move-json-file 
topics-to-move.json --broker-list "0,1,2,3" --generate
Current partition replica assignment
{"version":1,"partitions":[{"topic":"first","partition":0,"replic
as":[0,2,1],"log_dirs":["any","any","any"]},{"topic":"first","par
tition":1,"replicas":[2,1,0],"log_dirs":["any","any","any"]},{"to
pic":"first","partition":2,"replicas":[1,0,2],"log_dirs":["any","
any","any"]}]}
Proposed partition reassignment configuration
{"version":1,"partitions":[{"topic":"first","partition":0,"replic
as":[2,3,0],"log_dirs":["any","any","any"]},{"topic":"first","par
tition":1,"replicas":[3,0,1],"log_dirs":["any","any","any"]},{"to
pic":"first","partition":2,"replicas":[0,1,2],"log_dirs":["any","
any","any"]}]}

(3)创建副本存储计划(所有副本存储在 broker0、broker1、broker2、broker3 中)。

[atguigu@hadoop102 kafka]$ vim increase-replication-factor.json

输入如下内容:

{"version":1,"partitions":[{"topic":"first","partition":0,"replic
as":[2,3,0],"log_dirs":["any","any","any"]},{"topic":"first","par
tition":1,"replicas":[3,0,1],"log_dirs":["any","any","any"]},{"to
pic":"first","partition":2,"replicas":[0,1,2],"log_dirs":["any","
any","any"]}]}

(4)执行副本存储计划。

[atguigu@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh --
bootstrap-server hadoop102:9092 --reassignment-json-file 
increase-replication-factor.json --execute

(5)验证副本存储计划。

[atguigu@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh --
bootstrap-server hadoop102:9092 --reassignment-json-file 
increase-replication-factor.json --verify
Status of partition reassignment:
Reassignment of partition first-0 is complete.
Reassignment of partition first-1 is complete.
Reassignment of partition first-2 is complete.
Clearing broker-level throttles on brokers 0,1,2,3
Clearing topic-level throttles on topic first

退役旧节点
1)执行负载均衡操作
先按照退役一台节点,生成执行计划,然后按照服役时操作流程执行负载均衡。
(1)创建一个要均衡的主题。

[atguigu@hadoop102 kafka]$ vim topics-to-move.json
{
 "topics": [
 {"topic": "first"}
 ],
 "version": 1
}

(2)创建执行计划。

[atguigu@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh --
bootstrap-server hadoop102:9092 --topics-to-move-json-file 
topics-to-move.json --broker-list "0,1,2" --generate
Current partition replica assignment
{"version":1,"partitions":[{"topic":"first","partition":0,"replic
as":[2,0,1],"log_dirs":["any","any","any"]},{"topic":"first","par
tition":1,"replicas":[3,1,2],"log_dirs":["any","any","any"]},{"to
pic":"first","partition":2,"replicas":[0,2,3],"log_dirs":["any","
any","any"]}]}
Proposed partition reassignment configuration
{"version":1,"partitions":[{"topic":"first","partition":0,"replic
as":[2,0,1],"log_dirs":["any","any","any"]},{"topic":"first","par
tition":1,"replicas":[0,1,2],"log_dirs":["any","any","any"]},{"to
pic":"first","partition":2,"replicas":[1,2,0],"log_dirs":["any","
any","any"]}]}

(3)创建副本存储计划(所有副本存储在 broker0、broker1、broker2 中)。

[atguigu@hadoop102 kafka]$ vim increase-replication-factor.json
{"version":1,"partitions":[{"topic":"first","partition":0,"replic
as":[2,0,1],"log_dirs":["any","any","any"]},{"topic":"first","par
tition":1,"replicas":[0,1,2],"log_dirs":["any","any","any"]},{"to
pic":"first","partition":2,"replicas":[1,2,0],"log_dirs":["any","
any","any"]}]}

(4)执行副本存储计划。

[atguigu@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 --reassignment-json-file 
increase-replication-factor.json --execute

(5)验证副本存储计划。

[atguigu@hadoop102 kafka]$ bin/kafka-reassign-partitions.sh --bootstrap-server hadoop102:9092 --reassignment-json-file 
increase-replication-factor.json --verify
Status of partition reassignment:
Reassignment of partition first-0 is complete.
Reassignment of partition first-1 is complete.
Reassignment of partition first-2 is complete.
Clearing broker-level throttles on brokers 0,1,2,3
Clearing topic-level throttles on topic first

2)执行停止命令
在 hadoop105 上执行停止命令即可。

[atguigu@hadoop105 kafka]$ bin/kafka-server-stop.sh

6.4 Kafka 副本

1)副本基本信息
(1)Kafka 副本作用:提高数据可靠性。
(2)Kafka 默认副本 1 个,生产环境一般配置为 2 个,保证数据可靠性;太多副本会
增加磁盘存储空间,增加网络上数据传输,降低效率。
(3)Kafka 中副本分为:Leader 和 Follower。Kafka 生产者只会把数据发往 Leader,
然后 Follower 找 Leader 进行同步数据。
(4)Kafka 分区中的所有副本统称为 AR(Assigned Repllicas)。
AR = ISR + OSR
ISR(能够正常通讯的,30s):表示和 Leader 保持同步的 Follower 集合。如果 Follower 长时间未向 Leader 发送
通信请求或同步数据,则该 Follower 将被踢出 ISR。该时间阈值由 replica.lag.time.max.ms
参数设定,默认 30s。Leader 发生故障之后,就会从 ISR 中选举新的 Leader。
OSR:表示 Follower 与 Leader 副本同步时,延迟过多的副本。

2)Leader 选举流程
Kafka 集群中有一个 broker 的 Controller 会被选举为 Controller Leader,负责管理集群
broker 的上下线,所有 topic 的分区副本分配和 Leader 选举等工作。
Controller 的信息同步工作是依赖于 Zookeeper 的。
在这里插入图片描述
选举规则如上图。

6.5 Leader 和 Follower 故障处理细节

在这里插入图片描述
在这里插入图片描述

6.6 文件存储

在这里插入图片描述
在这里插入图片描述
这是是使用的稀疏索引的方式,达到4kb才创建一个索引

6.7 高效读写数据

1)Kafka 本身是分布式集群,可以采用分区技术,并行度高
2)读数据采用稀疏索引,可以快速定位要消费的数据
3)顺序写磁盘
Kafka 的 producer 生产数据,要写入到 log 文件中,写的过程是一直追加到文件末端,
为顺序写。官网有数据表明,同样的磁盘,顺序写能到 600M/s,而随机写只有 100K/s。这
与磁盘的机械机构有关,顺序写之所以快,是因为其省去了大量磁头寻址的时间。
4)页缓存 + 零拷贝技术
在这里插入图片描述
所有处理数据都在生产和消费。

在这里插入图片描述

七 .Kafka 消费者

7.1 Kafka 消费方式

在这里插入图片描述

7.2 消费者总体工作流程

在这里插入图片描述
每个分区的数据只能由消费者组中一个消费者消费。
单个消费者也叫消费者组。

7.3 消费者组初始化流程

在这里插入图片描述

7.4 消费者组详细消费流程

sendFetches()方法的参数:
在这里插入图片描述
消费者重要参数

在这里插入图片描述
在这里插入图片描述

7.5 按照主题消费流程:

0)配置信息

Properties properties = new Properties();
连接集群
properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop102:9092");
反序列化(key和value都需要)
	// 配置序列化 必须
properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, 
StringDeserializer.class.getName());
 
properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
StringDeserializer.class.getName());
设置组id
	// 配置消费者组(必须),名字可以任意起
 properties.put(ConsumerConfig.GROUP_ID_CONFIG,"test");

1)创建消费者

KafkaConsumer<String, String> kafkaConsumer = new KafkaConsumer<>(properties);

2)订阅主题

// 注册要消费的主题(可以消费多个主题)
 ArrayList<String> topics = new ArrayList<>();
 topics.add("first");
 kafkaConsumer.subscribe(topics);
(这里还可以按照分区)
	// 消费某个主题的某个分区数据
 ArrayList<TopicPartition> topicPartitions = new 
ArrayList<>();
 topicPartitions.add(new TopicPartition("first", 0));
 kafkaConsumer.assign(topicPartitions);

注意:按照主题和分区最好调用的方法不同
3)消费数据

while (true){
 ConsumerRecords<String, String> consumerRecords = 
kafkaConsumer.poll(Duration.ofSeconds(1));
 for (ConsumerRecord<String, String> consumerRecord : 
consumerRecords) {
 System.out.println(consumerRecord);
 }
 }

要形成一个消费者组,择不同的消费者设置相同的组id

7.6 生产经验——分区的分配以及再平衡

1)range
求模,除不尽的给第一个消费者
容易产生数据倾斜
再平衡:其中一个挂了会将分区分发其他的消费者
在这里插入图片描述
2)RoundRobin
顺序
再平衡:其中一个挂了,分区轮寻给其他消费者,45s过后默认挂了的消费者退出,下一次分区消息重写轮寻
在这里插入图片描述

3)粘性
第一个随机操作,直到用完一个消费者
再平衡:其中一个挂了,尽量均匀的给到其他消费者

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值