Kafka 分布式消息系统
- [一、Kafka 概述](#一、Kafka 概述)
-
- [1.1 Kafka 定义](#1.1 Kafka 定义)
- [1.2 Kafka 设计目标](#1.2 Kafka 设计目标)
- [1.3 Kafka 特点](#1.3 Kafka 特点)
- [二、Kafka 架构设计](#二、Kafka 架构设计)
-
- [2.1 基本架构](#2.1 基本架构)
- [2.2 Topic 和 Partition](#2.2 Topic 和 Partition)
- [2.3 消费者和消费者组](#2.3 消费者和消费者组)
- [2.4 Replica 副本](#2.4 Replica 副本)
- [三、Kafka 分布式集群搭建](#三、Kafka 分布式集群搭建)
-
- [3.1 下载解压](#3.1 下载解压)
-
- [3.1.1 上传解压](#3.1.1 上传解压)
- [3.2 修改 Kafka 配置文件](#3.2 修改 Kafka 配置文件)
-
- [3.2.1 修改zookeeper.properties配置文件](#3.2.1 修改zookeeper.properties配置文件)
- [3.2.2 修改consumer.properties配置文件](#3.2.2 修改consumer.properties配置文件)
- [3.2.3 修改producer.properties配置](#3.2.3 修改producer.properties配置)
- [3.2.4 修改server.properties配置](#3.2.4 修改server.properties配置)
- [3.3 修改 Kafka 配置同步到其他节点](#3.3 修改 Kafka 配置同步到其他节点)
- [3.4 修改 Kafka Server 编号](#3.4 修改 Kafka Server 编号)
- [3.5 启动Kafka 集群](#3.5 启动Kafka 集群)
- [3.5.1 启动Zookeeper集群](#3.5.1 启动Zookeeper集群)
- [3.5.1 启动 Kafka 集群](#3.5.1 启动 Kafka 集群)
- [3.6 Kafka 集群测试](#3.6 Kafka 集群测试)
-
- [3.6.1 创建Topic](#3.6.1 创建Topic)
- [3.6.2 查看Topic列表](#3.6.2 查看Topic列表)
- [3.6.2 查看Topic详情](#3.6.2 查看Topic详情)
- [3.6.3 消费者消费Topic](#3.6.3 消费者消费Topic)
- [3.6.4 生产者向Topic发送消息](#3.6.4 生产者向Topic发送消息)
- [四、案例实践:Flume 与 Kafka 集成开发](#四、案例实践:Flume 与 Kafka 集成开发)
-
- [4.1 配置Flume聚合服务](#4.1 配置Flume聚合服务)
- [4.2 Flume与Kafka集成测试](#4.2 Flume与Kafka集成测试)
-
- [4.2.1 启动Flume聚合服务](#4.2.1 启动Flume聚合服务)
- [4.2.2 启动 Flume 采集服务](#4.2.2 启动 Flume 采集服务)
- [4.2.3 启动 Kafka 消费者服务](#4.2.3 启动 Kafka 消费者服务)
- [4.2.4 准备测试数据](#4.2.4 准备测试数据)
一、Kafka 概述
1.1 Kafka 定义
Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala语言编写,它以可水平扩展和高吞吐率的特点而被广泛使用。目前越来越多的开源分布式处理系统,如Spark、Flink都支持与Kafka集成。比如一个实时日志分析系统,Flume采集数据通过接口传输到Kafka集群(多台Kafka服务器组成的集群称为Kafka集群),然后Flink或者Spark直接调用接口从Kafka实时读取数据并进行统计分析。
1.2 Kafka 设计目标
- 以时间复杂度为O(1)的方式提供消息持久化(Kafka)能力,即使对TB级以上数据也能保证常数时间的访问性能。持久化是将程序数据在持久状态和瞬时状态间转换的机制。通俗地讲,就是瞬时数据(比如内存中的数据是不能永久保存的)持久化为持久数据(比如持久化至磁盘中能够长久保存)。
- 保证高吞吐率,即使在非常廉价的商用机器上,也能做到单机支持每秒100,000条消息的传输速度。
- 支持Kafka Server间的消息分区,以及分布式消息消费,同时保证每个Partition内的消息顺序传输。
- 支持离线数据处理和实时数据处理。
1.3 Kafka 特点
- 高吞吐量、低延迟:Kafka 每秒可以处理几十万条消息,它的延迟最低只有几毫秒。
- 可扩展性:Kafka集群同Hadoop集群一样,支持横向扩展。
- 持久性、可靠性:Kafka消息可以被持久化到本地磁盘,并且支持Partition数据备份,防止数据丢失。
- 容错性:允许Kafka集群中的节点失败,如果Partition(分区)副本数量为n,则最多允许n-1个节点失败。
- 高并发:单节点支持上千个客户端同时读写,每秒钟有上百MB的吞吐量,基本上达到了网卡的极限。
二、Kafka 架构设计
2.1 基本架构

生产者将数据写入 Kafka,消费者从 Kafka 中读取数据,Zookeeper 提供协调服务,如生产者和消费者的负载均衡
2.2 Topic 和 Partition

生产者将数据写入主题,实际写入分区(轮询,随机等),一个分区只能对应一个消费者组中的一个消费组,而一个消费者可以对应多个分区。
2.3 消费者和消费者组

一个分区只能对应一个消费者组中的一个消费者,消费者组相互独立,一个分区可以对应多个不同消费者组中的消费者,一个消费者可以对应多个分区。
2.4 Replica 副本
-
Leader:每个Replica集合中的分区都会选出一个唯一的Leader,所有的读写请求都由Leader处理,其他副本从Leader处把数据更新同步到本地。
-
Follower:是副本中的另外一个角色,可以从Leader中复制数据。
-
ISR:Kafka集群通过数据冗余来实现容错。每个分区都会有一个Leader,以及零个或多个Follower,Leader加上Follower总和就是副本因子。Follower与Leader之间的数据同步是通过Follower主动拉取Leader上面的消息来实现的。所有的Follower不可能与Leader中的数据一直保持同步,那么与Leader数据保持同步的这些Follower称为IS(In Sync Replica)。Zookeeper维护着每个分区的Leader信息和ISR信息。
三、Kafka 分布式集群搭建
3.1 下载解压
下载地址:https://archive.apache.org/dist/kafka/
此处使用的下载的版本式:kafka_2.12_2.8.2.tgz
3.1.1 上传解压
javascript
[root@hadoop1 local]# tar -zxvf kafka_2.12-2.8.2.tgz
添加软连接
javascript
[root@hadoop1 local]# ln -s kafka_2.12-2.8.2 kafka

3.2 修改 Kafka 配置文件
3.2.1 修改zookeeper.properties配置文件
进入Kafka的config目录下,修改zookeeper. properties配置文件,具体内容如下:
javascript
[root@hadoop1 local]# vim /usr/local/kafka/config/zookeeper.properties
修改如下内容:
javascript
dataDir=/usr/local/data/zookeeper/zkdata
clientPort=2181
3.2.2 修改consumer.properties配置文件
进入Kafka的config目录下,修改consumer. properties配置文件,具体内容如下:
javascript
[root@hadoop1 local]# vim /usr/local/kafka/config/consumer.properties
修改如下内容:
javascript
bootstrap.servers=hadoop1:9092,hadoop2:9092,hadoop3:9092
备注:hadoop1:9092,hadoop2:9092,hadoop3:9092 为集群hadoop地址
3.2.3 修改producer.properties配置
进入Kafka的config目录中,修改producer. properties配置文件,具体内容如下:
javascript
[root@hadoop1 local]# vim /usr/local/kafka/config/producer.properties
修改内容如下:
javascript
bootstrap.servers=hadoop1:9092,hadoop2:9092,hadoop3:9092
3.2.4 修改server.properties配置
进入Kafka的config目录下,修改server. properties配置文件,具体内容如下:
javascript
[root@hadoop1 local]# vim /usr/local/kafka/config/server.properties
修改内容如下:
javascript
zookeeper.connect=hadoop1:2181,hadoop2:2181,hadoop3:2181
3.3 修改 Kafka 配置同步到其他节点
将hadoop1节点中配置好的Kafka安装目录分发给hadoop2和hadoop3节点,具体操作如下所示:
javascript
[root@hadoop1 local]# deploy.sh /usr/local/kafka_2.12-2.8.2 /usr/local/ slave
给从节点创建软链接:
javascript
[root@hadoop1 local]# runRemoteCmd.sh "ln -s /usr/local/kafka_2.12-2.8.2 /usr/local/kafka" slave
备注:deploy.sh 是集群推送脚本,可以参考《ZooKeeper 集群的详细部署》
3.4 修改 Kafka Server 编号
登录hadoop1、hadoop2和hadoop3节点,分别进入Kafka的config目录下,修改server.properties配置文件中的broker.id项,具体操作如下所示:
root@hadoop1 local\]# vim /usr/local/kafka/config/server.properties #标识hadoop1节点 broker.id=1 \[root@hadoop2 local\]# vim /usr/local/kafka/config/server.properties #标识hadoop2节点 broker.id=2 \[root@hadoop3 local\]# vim /usr/local/kafka/config/server.properties #标识hadoop3节点 broker.id=3 ### 3.5 启动Kafka 集群 Zookeeper管理着Kafka Broker集群,同时Kafka将元数据信息保存在Zookeeper中,说明Kafka集群依赖Zookeeper提供协调服务,所以需要先启动Zookeeper集群,然后再启动Kafka集群。 ### 3.5.1 启动Zookeeper集群 在集群各个节点中进入Zookeeper安装目录,使用如下命令启动Zookeeper集群。 ```javascript # 启动集群 [root@hadoop1 local]# runRemoteCmd.sh "/usr/local/zookeeper/bin/zkServer.sh start" all # 查看zookeeper 集群状态 [root@hadoop1 local]# runRemoteCmd.sh "/usr/local/zookeeper/bin/zkServer.sh status" all ```  ### 3.5.1 启动 Kafka 集群 在集群各个节点中进入Kafka安装目录,使用如下命令启动Kafka集群。 ```javascript [root@hadoop1 local]# runRemoteCmd.sh "/usr/local/kafka/bin/kafka-server-start.sh -daemon /usr/local/kafka/config/server.properties" all ```  显示 Kafka 已经启动。 ### 3.6 Kafka 集群测试 Kafka自带有很多种Shell脚本供用户使用,包含生产消息、消费消息、Topic管理等功能。接下来利用Kafka Shell脚本测试使用Kafka集群。 #### 3.6.1 创建Topic 使用Kafka的bin目录下的kafka-topics.sh脚本,通过create命令创建名为test的Topic,具体操作如下所示。 ```javascript [root@hadoop1 local]# /usr/local/kafka/bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic test --replication-factor 3 --partitions 3 ``` 上述命令中,--zookeeper 指定 Zookeeper 集群;--create 是创建 Topic 命令;--topic指定Topic名称;--replication-factor 指定副本数量;--partitions指定分区个数。  #### 3.6.2 查看Topic列表 通过list命令可以查看Kafka 的Topic列表,具体操作如下所示。 ```javascript [root@hadoop1 kafka]# /usr/local/kafka/bin/kafka-topics.sh --zookeeper hadoop1:2181 --list ```  #### 3.6.2 查看Topic详情 通过describe命令查看Topic内部结构,具体操作如下所示。 ```javascript [root@hadoop1 kafka]# /usr/local/kafka/bin/kafka-topics.sh --zookeeper hadoop1:2181 --describe --topic test ```  #### 3.6.3 消费者消费Topic 在hadoop1节点上,通过Kafka自带的kafka-console-consumer.sh脚本,开启消费者消费 test中的消息。 ```javascript [root@hadoop1 kafka]# /usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server hadoop1:9092 --topic test ```  #### 3.6.4 生产者向Topic发送消息 在hadoop1节点上,通过Kafka自带的kafka-console-producer.sh脚本启动生产者,然后向 test发送3条消息,具体操作如下所示。 ```javascript [root@hadoop1 logs]# /usr/local/kafka/bin/kafka-console-producer.sh --broker-list hadoop1:9092 --topic test ``` 生成者输入:  消费者展示:  ## 四、案例实践:Flume 与 Kafka 集成开发 在 [《Flume 日志采集系统》](https://blog.csdn.net/slb190623/article/details/141942856?spm=1001.2014.3001.5501) 的基础上进行 kafka 集成开发 ### 4.1 配置Flume聚合服务 在 hadoop2 和 hadoop3 服务器配置分配配置 Flume 聚合服务 ```javascript [root@hadoop1 conf]# vim /usr/local/flume/conf/avro-file-selector-kafka.properties [root@hadoop2 conf]# vim /usr/local/flume/conf/avro-file-selector-kafka.properties ``` 分别写入如下内容并保存: ```javascript #定义source、channel、sink的名称 agent1.sources = r1 agent1.channels = c1 agent1.sinks = k1 # 定义和配置一个avro Source agent1.sources.r1.type = avro agent1.sources.r1.channels = c1 agent1.sources.r1.bind = 0.0.0.0 agent1.sources.r1.port = 1234 # 定义和配置一个file channel agent1.channels.c1.type = file agent1.channels.c1.checkpointDir = /usr/local/data/flume/checkpointDir agent1.channels.c1.dataDirs = /usr/local/data/flume/dataDirs # 定义和配置一个kafka sink agent1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink agent1.sinks.k1.topic = test agent1.sinks.k1.brokerList = hadoop1:9092,hadoop2:9092,hadoop3:9092 agent1.sinks.k1.producer.acks = 1 agent1.sinks.k1.channel = c1 ``` ### 4.2 Flume与Kafka集成测试 #### 4.2.1 启动Flume聚合服务 在 采集服务器 hadoop2 和 hadoop3 分别启动聚合服务 ```javascript [root@hadoop2 conf]# /usr/local/flume/bin/flume-ng agent -n agent1 -c conf -f /usr/local/flume/conf/avro-file-selector-kafka.properties -Dflume.root.logger=INFO,console [root@hadoop3 local]# /usr/local/flume/bin/flume-ng agent -n agent1 -c conf -f /usr/local/flume/conf/avro-file-selector-kafka.properties -Dflume.root.logger=INFO,console ```  #### 4.2.2 启动 Flume 采集服务 在 Hadoop1 启动 Flume 采集脚本: ```javascript [root@hadoop1 conf]# /usr/local/flume/bin/flume-ng agent -n agent1 -c conf -f /usr/local/flume/conf/taildir-file-selector-avro.properties -Dflume.root.logger=INFO,console ```  正常启动 Flume 采集脚本 #### 4.2.3 启动 Kafka 消费者服务 在 hadoop1 启动 Kafka 消费者服务脚本 ```javascript [root@hadoop1 data]# /usr/local/kafka/bin/kafka-console-consumer.sh --bootstrap-server hadoop1:9092 --topic test ```  #### 4.2.4 准备测试数据 在 hadoop1 另开连接,执行如下脚本: ```javascript [root@hadoop1 logs]# echo '00:00:100971413028304674[火炬传递路线时间]1 2www.olympic.cn/news/beijing/2008-03-19/1417291.html' >> /usr/local/data/flume/logs/sogou.log ``` 输入三条测试数据  消费者打印三条测试数据:  至此,案例测试成功。