Kafka消息队列

一、消息队列

1、什么是消息队列

消息(Message)是指在应用间传送的数据。消息可以非常简单,比如只包含文本字符串,也可以更复杂,可能包含嵌入对象。

消息队列(Message Queue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ 中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在

2、消息队列的特性:

特征 具体内容
存储 与依赖使用套接字的基本 TCP 和 UDP 协议的传统请求和响应系统不同,消息队列通常将消息存储在某种类型的缓冲区中,直到目标进程读取这些消息或将其从消息队列中显式移除为止
异步 与请求和响应系统不同,消息队列通过缓冲消息可以在应用程序中实现一定程度的异步性,允许源进程发送消息并在队列中累积消息,而目标进程则可以挑选消息进行处理。这样,应用程序就可以在某些故障情况下运行,例如连接断断续续或源进程或目标进程故障。 路由:消息队列还可以提供路由功能,其中多个进程可以在同一队列中读取或写入消息,从而实现广播或单播通信模式

3、消息队列的作用:

特性 描述
解耦 允许独立扩展或修改两边处理过程,确保遵守同样接口约束
冗余 消息队列持久化数据直至完全处理,"插入 - 获取 - 删除" 范式确保数据安全保存到使用完毕,规避数据丢失风险
扩展性 因解耦处理过程,增加消息入队和处理频率易,只需增加处理过程
灵活性 & 峰值处理能力 访问量剧增时,使关键组件顶住突发压力,避免因突发超负荷请求崩溃,避免以峰值访问为标准投入资源的浪费
可恢复性 部分组件失效不影响整个系统,降低进程间耦合度,进程挂掉后队列消息可在系统恢复后处理
顺序保证 大多场景下数据处理顺序重要,大部分消息队列排序,能保证按特定顺序处理(如 Kafka 保证一个 Partition 内消息有序性 )
缓冲 有助于控制和优化数据流速度,解决生产与消费消息处理速度不一致问题
异步通信 提供异步处理机制,允许用户放入消息不立即处理,需用时再处理

二.Kafka 基础与入门

1.Kafka 基本概念

Kafka 是一种高吞吐量的分布式发布 / 订阅消息系统,这是官方对 kafka 的定义,这样说起来,可能不太好理解,这里简单举个例子:现在是个大数据时代,各种商业、社交、搜索、浏览都会产生大量的数据。那么如何快速收集这些数据,如何实时的分析这些数据,是一个必须要解决的问题,同时,这也形成了一个业务需求模型,即生产者生产(produce)各种数据,消费者(consume)消费(分析、处理)这些数据。那么面对这些需求,如何高效、稳定的完成数据的生产和消费呢?这就需要在生产者与消费者之间,建立一个通信的桥梁,这个桥梁就是消息系统。从微观层面来说,这种业务需求也可理解为不同的系统之间如何传递消息。

kafka 是 Apache 组织下的一个开源系统,它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于 hadoop 平台的数据分析、低时延的实时系统、storm/spark 流式处理引擎等。kafka 现在已被多家大型公司作为多种类型的数据管道和消息系统使用

2、kafka相关术语

术语 解释
Broker Kafka 集群包含一个或多个服务器,每个服务器被称为 broker(经纪人)
Topic 每条发布到 Kafka 集群的消息都有一个分类,这个类别被称为 Topic(主题)
Producer 指消息的生产者,负责发布消息到 kafka broker
Consumer 指消息的消费者,从 kafka broker 拉取数据,并消费这些已发布的消息
Partition Partition 是物理上的概念,每个 Topic 包含一个或多个 Partition,每个 partition 都是一个有序的队列。partition 中的每条消息都会被分配一个有序的 id(offset)
Consumer Group 消费者组,可以给每个 Consumer 指定消费组,若不指定消费者组,则属于默认的 group
Message 消息,通信的基本单位,每个 producer 可以向一个 topic 发布一些消息

3、 Kafka 拓扑架构

一个典型的 Kafka 集群包含若干 Producer,若干 broker、若干 Consumer Group,以及一个 Zookeeper 集群。Kafka 通过 Zookeeper 管理集群配置,选举 leader,以及在 Consumer Group 发生变化时进行 rebalance。Producer 使用 push 模式将消息发布到 broker,Consumer 使用 pull 模式从 broker 订阅并消费消息。典型架构如下

分类 详情
组成与消费规则 典型消息系统由生产者(Producer)、存储系统(broker )、消费者(Consumer)组成;Kafka 支持多生产者、多消费者,生产者可将消息分布到集群不同节点不同 Partition,写消息允许多生产者写同一 Partition,读消息时一个 Partition 仅允许被一个消费组的一个消费者消费,一个消费者可消费多个 Partition,同一消费组下消费者对 Partition 互斥,不同消费组间共享
持久化存储 Kafka 支持消息持久化存储,数据存在日志文件;生产者生产消息后先存于 broker,broker 会暂存消息,当消息个数、尺寸等达阈值时统一写入磁盘,可提升执行效率、减少磁盘 IO 调用次数
写入机制与优势 Kafka 中消息到 partition 是顺序写入磁盘,机械盘下顺序写入效率远高于随机写入,此机制是 Kafka 高吞吐率的重要保证

4、Topic 与 partition

Kafka 中的 topic(主题)是以 partition 的形式存放的,每一个 topic 都可以设置它的 partition 数量,Partition 的数量决定了组成 topic 的 log 的数量。推荐 partition 的数量一定大于同时运行的 consumer 的数量。另外,建议 partition 的数量要小于等于集群 broker 的数量,这样消息数据就可以均匀的分布在各个 broker 中。

那么,Topic 为什么要设置多个 Partition 呢,这是因为 kafka 是基于文件存储的,通过配置多个 partition 可以将消息内容分散存储到多个 broker 上,这样可以避免文件尺寸达到单机磁盘的上限。同时,将一个 topic 切分成任意多个 partitions,可以保证消息存储、消息消费的效率,因为越多的 partitions 可以容纳更多的 consumer,可有效提升 Kafka 的吞吐率。因此,将 Topic 切分成多个 partitions 的好处是可以将大量的消息分成多批数据同时写到不同节点上,将写请求分担负载到各个集群节点。

在存储结构上,每个 partition 在物理上对应一个文件夹,该文件夹下存储这个 partition 的所有消息和索引文件。partition 命名规则为 topic 名称 - 序号,第一个 partition 序号从 0 开始,序号最大值为 partitions 数量减 1。

在每个 partition(文件夹)中有多个大小相等的 segment(数据文件),每个 segment 的大小是相同的,但是每条消息的大小可能不相同,因此 segment(.log)数据文件中消息数量不一定相等。segment 数据文件有两个部分组成,分别为 index file 和 data file,此两个文件是一一对应,成对出现,后缀 ".index" 和 ".log" 分别表示为 segment 索引文件和数据文件。

5、Producer 生产机制

Producer 是消息和数据的生产者,它发送消息到 broker 时,会根据 Partition 机制选择将其存储到哪一个 Partition。如果 Partition 机制设置的合理,所有消息都可以均匀分布到不同的 Partition 里,这样就实现了数据的负载均衡。如果一个 Topic 对应一个文件,那这个文件所在的机器 I/O 将会成为这个 Topic 的性能瓶颈,而有了 Partition 后,不同的消息可以并行写入不同 broker 的不同 Partition 里,极大的提高了吞吐率。

6.、Consumer 消费机制

Kafka 发布消息通常有两种模式:队列模式(queuing)和发布 / 订阅模式(publisher - subscribe)。在队列模式下,只有一个消费组,而这个消费组有多个消费者,一条消息只能被这个消费组中的一个消费者所消费;而在发布 / 订阅模式下,可有多个消费组,每个消费组只有一个消费者,同一条消息可被多个消费组消费。

Kafka 中的 producer 和 consumer 采用的是 push、pull 的模式,即 producer 向 broker 进行 push 消息,consumer 从 bork 进行 pull 消息,push 和 pull 对于消息的生产和消费是异步进行的。pull 模式的一个好处是 consumer 可自主控制消费消息的速率,同时 consumer 还可以自己控制消费消息的方式是批量的从 broker 拉取数据还是逐条消费数据

三、Zookeeper 概念介绍

ZooKeeper 是一种分布式协调技术,所谓分布式协调技术主要是用来解决分布式环境当中多个进程之间的同步控制,让他们有序的去访问某种共享资源,防止造成资源竞争(脑裂)的后果。脑裂是指在主备切换时,由于切换不彻底或其他原因,导致客户端和 Slave 误以为出现两个 activemaster,最终使得整个集群处于混乱状态

这里首先介绍下什么是分布式系统,所谓分布式系统就是在不同地域分布的多个服务器,共同组成的一个应用系统来为用户提供服务,在分布式系统中最重要的是进程的调度,这里假设有一个分布在三个地域的服务器组成的一个应用系统,在第一台机器上挂载了一个资源,然后这三个地域分布的应用进程都要竞争这个资源,但我们又不希望多个进程同时进行访问,这个时候就需要一个协调器(锁),来让它们有序的来访问这个资源。这个协调器就是分布式系统中经常提到的那个锁,例如进程 1 在使用该资源的时候,会先去获得这把锁,进程 1 获得锁以后会对该资源保持独占,此时其它进程就无法访问该资源,进程 1 在用完该资源以后会将该锁释放掉,以便让其它进程来获得锁。由此可见,通过这个锁机制,就可以保证分布式系统中多个进程能够有序的访问该共享资源。这里把这个分布式环境下的这个锁叫作分布式锁。这个分布式锁就是分布式协调技术实现的核心内容。

目前,在分布式协调技术方面做得比较好的有 Google 的 Chubby,还有 Apache 的 ZooKeeper,它们都是分布式锁的实现者。ZooKeeper 所提供锁服务在分布式领域久经考验,它的可靠性、可用性都是经过理论和实践验证的。

ZooKeeper 是一种为分布式应用所设计的高可用、高性能的开源协调服务,它提供了一项基本服务:分布式锁服务,同时,也提供了数据的维护和管理机制,如:统一命名服务、状态同步服务、集群管理、分布式消息队列、分布式应用配置项的管理等等。

1、zookeeper 应用举例

1.1、什么是单点故障问题呢?

所谓单点故障,就是在一个主从的分布式系统中,主节点负责任务调度分发,从节点负责任务的处理,而当主节点发生故障时,整个应用系统也就瘫痪了,那么这种故障就称为单点故障。那我们的解决方法就是通过对集群 master 角色的选取,来解决分布式系统单点故障的问题。

1.2、传统的方式是怎么解决单点故障的?以及有哪些缺点呢?

传统的方式是采用一个备用节点,这个备用节点定期向主节点发送 ping 包,主节点收到 ping 包以后向备用节点发送回复 Ack 信息,当备用节点收到回复的时候就会认为当前主节点运行正常,让它继续提供服务。而当主节点故障时,备用节点就无法收到回复信息了,此时,备用节点就认为主节点宕机,然后接替它成为新的主节点继续提供服务。

这种传统解决单点故障的方法,虽然在一定程度上解决了问题,但是有一个隐患,就是网络问题,可能会存在这样一种情况:主节点并没有出现故障,只是在回复 ack 响应的时候网络发生了故障,这样备用节点就无法收到回复,那么它就会认为主节点出现了故障,接着,备用节点将接管主节点的服务,并成为新的主节点,此时,分布式系统中就出现了两个主节点(双 Master 节点)的情况,双 Master 节点的出现,会导致分布式系统的服务发生混乱。这样的话,整个分布式系统将变得不可用。为了防止出现这种情况,就需要引入 ZooKeeper 来解决这种问题。

2、zookeeper的工作原理是什么?

情形 具体过程
master 启动 在分布式系统引入 Zookeeper 后,配置多个主节点(以主节点 A、B 为例),两节点启动后向 Zookeeper 注册节点信息(A 为 master00001 ,B 为 master00002 ),以编号最小算法选举,编号小的 A 获锁成为主节点,B 阻塞为备用节点,完成主、备节点分配协作
master 故障 主节点 A 故障,其在 Zookeeper 注册的节点信息自动删除,Zookeeper 感知变化后再次选举,主节点 B 获胜成为新主节点,完成主、被节点重新选举
master 恢复 主节点 A 恢复后,向 Zookeeper 注册新节点信息(master00003 ),Zookeeper 感知变化再次选举,主节点 B 再次获胜继续担任主节点,A 任备用节点

3、zookeeper 集群架构

zookeeper 一般是通过集群架构来提供服务的,下图是 zookeeper 的基本架构图

角色类型 具体角色 角色含义
server Leader 领导者角色,主要负责投票的发起和决议,以及更新系统状态
server follower 跟随者角色,用于接收客户端的请求并返回结果给客户端,在选举过程中参与投票
server observer 观察者角色,用于接收客户端的请求,并将写请求转发给 leader,同时同步 leader 状态,但是不参与投票,目的是扩展系统,提高伸缩性
client client 客户端角色,用于向 zookeeper 发起请求

4、zookeeper 的工作流程

流程类型 具体流程描述
Zookeeper 修改数据流程 Zookeeper 集群中每个 Server 在内存中存储一份数据,启动时从实例选举一个 Server 作为 leader;Leader 负责处理数据更新等操作,当且仅当大多数 Server 在内存中成功修改数据,才认为数据修改成功
Zookeeper 写流程 客户端 Client 先和一个 Server 或 Observe 通信发起写请求;Server 将写请求转发给 Leader,Leader 再转发给其它 Server;其它 Server 接收写请求后写入数据并响应 Leader;Leader 收到大多数写成功回应后,认为数据写成功,最后响应 Client,完成一次写操作过程

四、Zookeeper 在 Kafka 中的作用

1. Broker 注册

Broker 是分布式部署且相互独立,需注册系统管理集群 Broker ,借助 Zookeeper ,其有专门节点 /brokers/ids 记录 Broker 服务器列表。

每个 Broker 启动时,在 Zookeeper 的 /brokers/ids 下创建自身节点(如 /brokers/ids/[0...N] )。Kafka 用全局唯一数字作 Broker ID ,不同 Broker 需不同 ID 注册。创建节点后,Broker 将自身 IP 地址和端口信息记录其中,且节点为临时节点,Broker 宕机则对应节点自动删除 。

2. Topic 注册

Kafka 中同一 Topic 消息分多个分区分布在多个 Broker ,分区信息及与 Broker 对应关系由 Zookeeper 维护,对应节点 /brokers/topics

每个 Topic 以 /brokers/topics/[topic] 形式记录(如 /brokers/topics/login/brokers/topics/search 等 )。Broker 启动后,会到对应 Topic 节点(/brokers/topics/[topic] )注册,写入自身 Broker ID 及 Topic 分区总数(如 /brokers/topics/login/3->2 ,表示 Broker ID 为 3 的服务器,对 "login" Topic 提供 2 个分区存储消息 ),该分区节点也为临时节点 。

3. 生产者负载均衡

由于同一个 Topic 消息会被分区并将其分布在多个 Broker 上,因此,生产者需要将消息合理地发送到这些分布式的 Broker 上,那么如何实现生产者的负载均衡,Kafka 支持传统的四层负载均衡,也支持 Zookeeper 方式实现负载均衡。

3.1、四层负载均衡

根据生产者的 IP 地址和端口来为其确定一个相关联的 Broker。通常,一个生产者只会对应单个 Broker,然后该生产者产生的消息都发往该 Broker。这种方式逻辑简单,每个生产者不需要同其他系统建立额外的 TCP 连接,只需要和 Broker 维护单个 TCP 连接即可。但是,其无法做到真正的负载均衡,因为实际系统中的每个生产者产生的消息量及每个 Broker 的消息存储量都是不一样的,如果有些生产者产生的消息远多于其他生产者的话,那么会导致不同的 Broker 接收到的消息总数差异巨大,同时,生产者也无法实时感知到 Broker 的新增和删除。

3.2、使用 Zookeeper 进行负载均衡

由于每个 Broker 启动时,都会完成 Broker 注册过程,生产者会通过该节点的变化来动态地感知到 Broker 服务器列表的变更,这样就可以实现动态的负载均衡机制。

4. 消费者负载均衡

与生产者类似,Kafka 中的消费者同样需要进行负载均衡来实现多个消费者合理地从对应的 Broker 服务器上接收消息,每个消费者分组包含若干消费者,每条消息都只会发送给分组中的一个消费者,不同的消费者分组消费自己特定的 Topic 下面的消息,互不干扰。

5. 记录消息分区与消费者的关系

消费组(Consumer Group)下有多个 Consumer(消费者)。对于每个消费者组(Consumer Group),Kafka 都会为其分配一个全局唯一的 Group ID,Group 内部的所有消费者共享该 ID。订阅的 topic 下的每个分区只能分配给某个 group 下的一个 consumer(当然该分区还可以被分配给其他 group)。

同时,Kafka 为每个消费者分配一个 Consumer ID,通常采用 "Hostname:UUID" 形式表示。

在 Kafka 中,规定了每个消息分区只能被同组的一个消费者进行消费,因此,需要在 Zookeeper 上记录消息分区与 Consumer 之间的关系,每个消费者一旦确定了对一个消息分区的消费权力,需要将其 Consumer ID 写入到 Zookeeper 对应的消息分区的临时节点上,例如:/consumers/[group_id]/owners/[topic]/[broker_id - partition_id] ,其中,[broker_id - partition_id] 就是一个消息分区的标识,节点内容就是该消息分区上消费者的 Consumer ID

6. 消息消费进度 Offset 记录

在消费者对指定消息分区进行消息消费的过程中,需定时将分区消息的消费进度 Offset 记录到 Zookeeper 上,以便消费者重启或其他消费者接管该消息分区消费后,从之前进度继续消费。Offset 在 Zookeeper 中由专门节点记录,节点路径为:/consumers/[group_id]/offsets/[topic]/[broker_id - partition_id] ,节点内容是 Offset 的值。

7. 消费者注册

内容分类 具体描述
注册到消费者分组 每个消费者服务器启动时,到 Zookeeper 指定节点(如 /consumers/[group_id]/ids/[consumer_id] )下创建自己的消费者节点, 并将订阅的 Topic 信息写入该节点
对消费者分组中的消费者变化注册监听 关注所属消费者分组中其他消费者服务器变化,对 /consumers/[group_id]/ids 节点注册子节点变化的 Watcher 监听, 发现消费者新增或减少,触发负载均衡
对 Broker 服务器变化注册监听 对 /broker/ids/[0 - N] 中的节点监听,Broker 服务器列表变化时, 据情况决定是否进行消费者负载均衡
进行消费者负载均衡 让同一个 Topic 下不同分区消息尽量均衡被多个消费者消费,对消费者与消息分区进行分配; 消费者分组内消费者或 Broker 服务器变更,会触发负载均衡
[消费者服务器在初始化启动时加入消费者分组的步骤]

五、集群部署Kafka

1、资源列表

操作系统 IP 主机名 应用
OpenEuler24 192.168.10.101 kafka1 Zookeeper,kafka
OpenEuler24 192.168.10.102 kafka2 Zookeeper,kafka
OpenEuler24 192.168.10.103 kafka3 Zookeeper,kafka

2、基础环境配置

2.1、修改主机名

bash 复制代码
hostnamectl set-hostname kafka1
hostnamectl set-hostname kafka2
hostnamectl set-hostname kafka3

2.2、关闭防火墙及内核保护

bash 复制代码
systemctl stop firewalld
setenforce 0

2.3、添加地址映射

bash 复制代码
vim /etc/hosts

###添加内容###
192.168.10.101 kafka1
192.168.10.102 kafka2
192.168.10.103 kafka3

2.4、安装依赖环境

bash 复制代码
dnf -y install java

3、三个节点安装ZooKeeper

bash 复制代码
tar -zxvf apache-zookeeper-3.6.0-bin.tar.gz

移动至合适位置
mv apache-zookeeper-3.6.0-bin /etc/zookeeper

#创建数据目录
mkdir -p /etc/zookeeper/zookeeper-data

#将配置文件例子拷贝一份并改名
cp zoo_sample.cfg zoo.cfg

#修改配置文件
vim zoo.cfg

###编辑内容###
dataDir=/etc/zookeeper/zookeeper-data
clientPort=2181
server.1=192.168.10.101:2888:3888
server.2=192.168.10.102:2888:3888
server.3=192.168.10.103:2888:3888

创建节点ID
echo "1" /etc/zookeeper/zookeeper-data/myid
echo "2" /etc/zookeeper/zookeeper-data/myid
echo "3" /etc/zookeeper/zookeeper-data/myid


#启动服务
./etc/zookeeper/bin/zkServer.sh start
端口号 用途说明
2181 对 client 端提供服务
3888 选举 leader 使用
2888 集群内机器通讯使用(Leader 监听此端口)

4、安装Kafka

bash 复制代码
tar -zxvf kafka_2.13-2.4.1.tgz

mv kafka_2.13-2.4.1 /etc/kafka

cd /etc/kafka/

mkdir kafka-logs

编辑配置文件

bash 复制代码
vim config/server.properties

###编辑内容###
broker.id=1
listeners=PLAINTEXT://192.168.10.101:9092
log.dirs=/etc/kafka/kafka-logs
num.partitions=1
zookeeper.connect=192.168.10.10:2181,192.168.10.102:2181,192.168.10.103:2181
bash 复制代码
vim config/server.properties

###编辑内容###
broker.id=2
listeners=PLAINTEXT://192.168.10.102:9092
log.dirs=/etc/kafka/kafka-logs
num.partitions=1
zookeeper.connect=192.168.10.10:2181,192.168.10.102:2181,192.168.10.103:2181
bash 复制代码
vim config/server.properties

###编辑内容###
broker.id=3
listeners=PLAINTEXT://192.168.10.103:9092
log.dirs=/etc/kafka/kafka-logs
num.partitions=1
zookeeper.connect=192.168.10.10:2181,192.168.10.102:2181,192.168.10.103:2181

启动服务

bash 复制代码
./etc/kafkaka/bin/fka-server-start.sh /etc/kafka/config/server.properties &

5、测试

创建topic

bash 复制代码
./etc/kafkaka/bin/kafka-topics.sh --create --zookeeper kafka1:2181 --replication-factor 1 --partitions 1 --topic aaa

生产消息

bash 复制代码
./etc/kafkaka/bin/kafka-console-producer.sh --broker-list kafka1:9092 -topic aaa

消费消息

bash 复制代码
./etc/kafkaka/bin/kafka-console-consumer.sh --bootstrap-server kafka1:9092 --topic aaa
相关推荐
Edingbrugh.南空11 分钟前
Flink Connector Kafka深度剖析与进阶实践指南
大数据·flink·kafka
Bug退退退1238 小时前
RabbitMQ 的工作流程
分布式·rabbitmq
roman_日积跬步-终至千里8 小时前
【分布式理论】读确认数与写确认数:分布式一致性的核心概念
分布式
网硕互联的小客服9 小时前
高并发下分布式数据库性能下降的解决方法
数据库·分布式
程序员小刘9 小时前
如何优化HarmonyOS 5的分布式通信性能?
分布式·华为·harmonyos5
转码的小石12 小时前
深入Java面试:从Spring Boot到微服务
java·spring boot·kafka·spring security·oauth2
蓝宗林18 小时前
Spark 以及 spark streaming 核心原理及实践
大数据·分布式·spark
李明一.18 小时前
Spark 技术与实战学习心得:从入门到实践的深度探索
大数据·分布式·spark
计算机毕设定制辅导-无忧学长20 小时前
Kafka 与其他 MQ 的对比分析:RabbitMQ/RocketMQ 选型指南(二)
kafka·rabbitmq·rocketmq