消息队列之-Kafka

405 阅读12分钟

1. Kafka 简介及使用场景

1.1 写在前面

我们提到消息中间件,往往都会聊到,RabbitMQ,RocketMQ,Kafka。 对于刚入门消息中间件,听到这三个主流消息中件,心中难免会有疑惑,这消息中间件搞这么多干什么?傻傻分不清楚,况且都是消息中间件,我开发中用哪个?知用而学,学以致用。本文将带你聊聊 Kafka ,让你知用,致用。

1.2 简介

官网:kafka.apache.org/

Kafka 是最初由 Linkedin 公司开发,是一个分布式、支持分区的(partition)、多副本的(replica)。基于 zookeeper 协调的分布式消息系统。 它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、Storm/Spark 流式处理引擎,web/nginx 日志、访问日志,消息服务等等,用scala语言编写。 Linkedin于2010年贡献给了Apache基金会并成为顶级开源 项目。

我摘取几个关键字给大家强调一下:

分布式消息系统基于 zookeeper大数据处理低延迟scala 开发

那么 Kafka 相较于 RabbitMQ、RocketMQ。更加适用于大数据处理的场景且强依赖于 zookeeper 。

1.3 使用场景

日志收集:

使用 Kafka 作为中间层收集各种服务的 log 日志,最后将消息发送给下游 consumer 进行消费处理,如 hadoop、hbase、soler 、es 等。

消息系统:

作为消息中间件,缓存消息,解耦上下游系统。

大数据收集运营监控处理分析:

用户活动跟踪、运营指标监控等一些分析型数据的收集分发处理等。 如记录 web 或者 app 用户各种活动记录,如 浏览、点击、搜索 等。这些活动信息被各个服务器发布到 kafka 的 topic 中,然后订阅者通过订阅这些 topic 来做实时的监控分析,或者装载到 hadoop、数据仓库中做离线分析和挖掘。

这里我给大家总结一个关键字 实时大数据分析与监控

其实相对于传统的消息中间件的用法上 Kafka 更偏向于大数据处理的体系上 ,属于 hadoop 全家桶的一员。那么我们对于消息中间件的常规使用,如应用解耦,削峰填谷上,我们会选择 RabbitMQ 、或者 RocketMQ 这类消息中间件

关于 RabbitMQ 欢迎阅读文章:消息队列之-RabbitMQ

2. Kafka 核心概念点

如果要了解 Kafka 首先需要搞懂其核心概念点,后面到架构就是顺水推舟的事情了。

在这里插入图片描述

Broker 消息中间件

一个 Kafka 节点就是一个 broker,一 个或者多个 Broker 可以组成一个 Kafka 集群

Topic 主题

Kafka 根据 topic 对消息进行归类,发布到 Kafka 集群的每条消息都需要指定一个 topic

Partition 分区

物理上的概念,一个 topic 可以分为多个 partition,每个 partition 内部消息是有序的

Producer 消息生产者

向 Broker 发送消息的客户端

Consumer 消息消费者

从 Broker 读取消息的客户端

ConsumerGroup 消费组

每个 Consumer 属于一个特定的 Consumer Group,一条消息可以被多个不同的 Consumer Group 消费,但是一个 Consumer Group 中只能有一个 Consumer 能够消费该消息。

相信如果看过我的上篇文章 消息队列之-RabbitMQ 的同学,或者了解过 RabbitMQ 的同学对上面这组概念都是比较熟悉了,相对于 RabbitMQ来说,Kafka 给出了几个陌生的概念 ,我这里给出一张图来对比一下

在这里插入图片描述 相对于 RabbitMQ 来说 Kafka 对消息的最终存储位置 “队列” 和消息消费方 “消费者” 做了更细致的分类。

Queue 和 Topic 的功能差不多 但是 Topic 下多了 partition 的概念,在 Kafka 中最终的数据时存储在 partition 分区中的,这个 Topic 分区化为服务的水平扩容带来了很大的便利,理论上这个存储是可以无限大的,只要你的机器够多。而对于 Consumer ,Kafka 又给出了更大的一层 Consumer Group ,以组为一个消费单位,不同的组内的消费者,相同的消息只可消费一次。

3. Kafka 安装

Kafka 是依赖于 Zookeeper 及 JDK 的所以在安装 Kafka 之前我们需要准备好 Zookeeper 及 JDK 环境。

安装 JDK

yum install java‐1.8.0‐openjdk* ‐y

下载安装 Zookeeper

wget https://mirror.bit.edu.cn/apache/zookeeper/zookeeper‐3.5.8/apache‐zookeeper‐3.5.8‐bin.tar.gz
tar ‐zxvf apache‐zookeeper‐3.5.8‐bin.tar.gz
cd apache‐zookeeper‐3.5.8‐bin 
cp conf/zoo_sample.cfg conf/zoo.cfg
# 启动zookeeper 
bin/zkServer.sh start 
bin/zkCli.sh 
ls / #查看zk的根目录相关节点

下载安装 Kafka

# 2.12是scala的版本,2.6.1是kafka的版本
# 404 可以直接访问 https://mirror.bit.edu.cn/apache/kafka 找到合适的地址
wget https://mirror.bit.edu.cn/apache/kafka/2.6.1/kafka_2.12-2.6.1.tgz
tar -xzf kafka_2.12-2.6.1.tgz
cd kafka_2.12-2.6.1

修改 Kafka 配置文件 config/server.properties

# 唯一标识 broker.id 该属性在 kafka 集群中必须是唯一 
broker.id=0
# kafka 部署的机器 ip 和提供服务的端口号 
listeners=PLAINTEXT://your.ip:9092
# kafka 的消息存储文件 
log.dir=/data/logs/kafka‐logs
# kafka 连接 zookeeper 的地址
zookeeper.connect=your.zk.ip:2181

Kafka 服务启动

基础语法 kafka-­server­-start.sh [­-daemon] server.properties

配置文件 server.properties 是必须的,-daemon 表示可以后台运行

# 启动 kafka,运行日志在 logs 目录的 server.log 文件里 
bin/kafka‐server‐start.sh ‐daemon config/server.properties 
# 后台启动,不会打印日志到控制台 或者
bin/kafka‐server‐start.sh config/server.properties &

server.properties 部分核心配置解释

参数默认值描述
broker.id0每个 broker 使用一个唯一的非负整数进行标识,你可以自定义但需要保证唯一
log.dirs/tmp/kafka-logs存放数据路径,可配置多个,使用英文逗号分隔。每当创建新的 partition 会选择分区最少的路径进行创建
listenersPLAINTEXT://:9092server 接受客户端连接的端口,ip 配置 kafka 本机 ip 即可,如 PLAINTEXT://localhost:9092
zookeeper.connectlocalhost:2181zookeeper 注册中心连接地址,多个使用英文逗号分隔
log.retention.hours168每个日志文件删除之前保存的时间。默认数据保存时间对所有 topic 都一样。
num.partitions1topic 默认分区数
default.replication.factor1自动创建 topic 的默认副本数量,建议设置为大于等于2
min.insync.replicas1当 producer 设置 acks 为 -1 时,min.insync.replicas 用于指定 replicas 的最小同步数目(必须确认每一个 repica 的写数据都是成功的),如果这个数目没有达到,producer发送消息会产生异常
delete.topic.enablefalse是否允许删除主题

4. 从命令行级别了解 Kafka 常用操作

创建主题

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic dyingGQ

成功:Created topic dyingGQ.

值得一提的是:当 producer 向一个 topic 发送消息且 topic 不存在时,该 topic 会被自动创建

查询存在的 topic 主题

bin/kafka-topics.sh --list --zookeeper localhost:2181

删除主题

bin/kafka-topics.sh --delete --topic dyingGQ --zookeeper localhost:2181
Topic dyingGQ is marked for deletion.
// 这里会提示你设置允许删除主题,否则不会有任何影响
Note: This will have no impact if delete.topic.enable is not set to true.

发送消息

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic dyingGQ 
>this is dying 搁浅
>hello kafka

消费消息

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic dyingGQ

该命令默认消费最新的消息,也就是说该命令执行后发送的消息可以消费到,如果想消费历史所有消息可添加参数 --from-beginning

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --from-beginning --topic dyingGQ

多主题消费

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --whitelist "dyingGQ|dyingGQ-1|dyingGQ-2"

单播消费

开启两个属于同组的消费者,同一组别下只有一个消费者可以消费到消息

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092  --consumer-property group.id=group1 --topic dyingGQ 
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092  --consumer-property group.id=group1 --topic dyingGQ 

多播消费

不同组可以同时消费同一条消息

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092  --consumer-property group.id=group2 --topic dyingGQ 

查看消费组名

bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --list

查看消费组消息偏移量

对于 Kafka 来说,它以组为单位来记录消息消费的偏移量来实现多播消息的消费,这样消息只需要存储一份即可 。

值得一提的是:消息的消费情况只与消费组绑定,与组下的消费者并无太大关系,即所有消费以组为准

bin/kafka-consumer-groups.sh --bootstrap-server localhost:9092 --describe --group group1

current-offset:当前消费组的已消费偏移量 log-end-offset:主题对应分区消息的结束偏移量(HW) lag:当前消费组未消费的消息数

5. Kafka 的存储与分区

总的来说,我认为消息队列最重要的,也是我们最应该关心的几点就是:消息的发送、消息的接收、消息的存储

对于发送和接收来说,相信通过上面的讲解大家心里大概都有一定的理解了,这个时候我们来聊聊存储。

Kafka 的存储以 Topic 主题为单位,下分为多个逻辑分区。就如同我们电脑存储要分多个磁盘,或者说我们单个磁盘下要分多个文件夹这样的关系。 在这里插入图片描述 partition 是一个 有序的消息序列 信息最终存储于 commit log 文件 中, partition 中的消息都对应一个唯一标识 offset 该存储位置即我们在 server.properties 中配置的 log.dirs 地址 在这里插入图片描述 如图中文稿所示 dyingGQ 为我们创建的话题,后面的编号 0 为分区编号。

创建多分区主题

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 2 --topic dyingGQ1

可以看到 Kafka 为我们的主题创建了两个分区的文件夹 dyingGQ1-0 以及 dyingGQ1-1 在这里插入图片描述 查看分区详情

bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic dyingGQ1

在这里插入图片描述

leader 该 partition 分区相对于备份来说负责所有读写请求。 replicas 表示某个 partition 在哪几个 broker 上存在备份。 isr 是 replicas 的一个子集,它只列出当前还存活着的,并且已同步备份了该 partition 的节点。

分区扩容

可以执行以下命令对我们已有的主题进行分区扩容

bin/kafka-topics.sh -alter --partitions 3 --zookeeper localhost:2181 --topic dyingGQ

可以看到执行成功后分区文件夹变成了 3 个 在这里插入图片描述 我们进入其中一个,真正的消息数据就存放在 .log 文件夹中 在这里插入图片描述 为什么 Topic 要进行 partition 分区? 我认为主要的理由两点:

  1. 方便水平扩容,分布式存储可支持海量数据。
  2. 可以提供并行处理能力。

6. Kafka 集群

以上,基础内容已经讲解完了,那么既然说到 Kafka ,集群是一定逃不开的。而对于 Kafka 来说其设计上就是天然的集群,单机可以理解为集群中只有一个节点。重要的一点是 Kafka 集群的主从关系是以分区即 partition 为单位的

在这里插入图片描述

尝试启动集群 我们可以在一台机器上启动多个 Kafka broker 实例来模拟真实的集群,为此我们需要创建多个 server.properties 文件并更改部分配置:

拷贝配置文件

cp config/server.properties config/server-1.properties
cp config/server.properties config/server-2.properties

修改配置文件信息 server-1.properties

broker.id=1
listeners=PLAINTEXT://192.168.65.60:9093
log.dir=/usr/local/data/kafka-logs-1
zookeeper.connect=192.168.65.60:2181

修改配置文件信息 server-2.properties

broker.id=2
listeners=PLAINTEXT://192.168.65.60:9094
log.dir=/usr/local/data/kafka-logs-2
zookeeper.connect=192.168.65.60:2181

启动多个实例

bin/kafka-server-start.sh -daemon config/server-1.properties
bin/kafka-server-start.sh -daemon config/server-2.properties

值得一提的是:Kafka 在启动 JVM 时默认 虚拟机堆大小 是 1G ,所以如果你的内存不够可以适当下调该值(至少大于等于 256M)

vim bin/kafka-server-start.sh

在这里插入图片描述 可以通过 zkCli 查看你的 Kafka 集群是否都已注册成功 在这里插入图片描述 在这里插入图片描述 在集群环境下创建多分区主题

bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 3 --partitions 2 --topic dyingGQ-replicated

查看 topic 主题详情

bin/kafka-topics.sh --describe --zookeeper localhost:2181 --topic dyingGQ-replicated

消息生产:

bin/kafka-console-producer.sh --broker-list localhost:9092,localhost:9093,localhost:9094 --topic dyingGQ-replicated
>my test msg 1
>my test msg 2

消费消息:

bin/kafka-console-consumer.sh --bootstrap-server localhost:9092,localhost:9093,localhost:9094 --from-beginning --topic my-replicated-topic
my test msg 1
my test msg 2

与之前的区别仅仅是增加了多台 Kafka 的地址而已。

7. 集群特性

集群 partition 备份

Kafka 支持设置针对每个 partition 备份,可以将 partition 备份到不同的 broker 上,其中 leader partition 负责读写,其他 follower 仅负责同步,当 leader 挂掉后会从 follower 中选取新的 leader

消息消费顺序

一个 partition 同一时刻在一个 consumer group 中只能有一个 consumer 实例在消费,从而保证了消费顺序。 consumer group 中的 consumer 实例的数量不能比一个 topic 中的 partition 的数量多,否则,多出来的 consumer 无法消费到消息

Kafka 的消息在单个 partition 上是可以保证顺序的,但是在整体上无法保证顺序消费

消息消费模式

关于消费模式,Kafka 通过 消费组的概念可以灵活设置 如常见的 队列模式 即 所有的 consumer 在同一个 consumer group 下。发布订阅模式 则设置多个 consumer group 进行消费即可

总结

最后做一个总结,本文首先带大家简单介绍了一下 Kafka 的使用场景以及一些核心概念点,重点要理清楚 topic 和 partition 以及 consumer group 和 consumer 的一个对应关系。带大家过了一遍 Kafka 的安装及命令行常规使用流程,以及数据的持久化存储,建议自己手动操作一遍加深印象。最后简单聊了聊集群相关的配置及特性。如果有相关问题可以在评论区留言,如果本文对你有所帮助,欢迎转发点赞收藏,喜欢我的文章欢迎关注公众号,有语音版本等你来听。 我是 dying 搁浅 我们下篇文章再见~ 在这里插入图片描述