目录
一:消息队列
1.什么是消息队列
2.消息队列的特征
3.为什么需要消息队列
二:Kafka基础与入门
1.Kafka基本概念
2.Kafka相关术语
3.Kafka拓扑架构
4.Topic与partition
5.Producer生产机制
6.Consumer消费机制
三:Zookeeper概念介绍
1.zookeeper应用举例
2.zookeeper的工作原理是什么?
3.zookeeper集群架构
4.zookeeper的工作流程
四:Zookeeper在Kafka中的作用
1.Broker注册
2.Topic注册
3.生产者负载均衡
4.消费者负载均衡
5.记录消费分区与消费者的关系
6.消息消费进度Offset记录
7.消费者注册
五:单节点部署Kafka
1.基础环境
2.安装Zookeeper
3.安装Kafka
4.测试
六:集群部署Kafka
1.资源列表
2.基础环境设置
3.安装zookeeper
4.安装kafka
5.测试
消息(Message)是指在应用间传送的数据。消息可以非常简单,比如只包含文
本字符串,也可以更复杂,可能包含嵌入对象。
消息队列(MessageQue)是一种应用间的通信方式,消息发送后可以立即返回,由消息系统来确保消息的可靠传递。消息发布者只管把泪消息发布到MQ中而不用管谁来取,消息使用者只管从MQ中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在。
(1)存储
与依赖于使用套接字的基本TCP和UDP协议的传统请求和味响应系统不同,消息队列通常将消息存储在某种类型的缓冲区中,直到目标进程读取这些消息或将其从消息队列中显式移除为止。
(2)异步
与请求和响应系统不同,消息队列通过缓冲消息可以在应用程序中实现一定程度的异步性,允许源进程发送消息并在队列中累积消息,而且标进程则可以挑选消息进行处理。这样,应用程序就可以在某些故障情况下运行,例如连接断断续续或源进程或目标进程故障。路由:消息队列还可以提供路由功能,其中多个进程可以在同一队列中读取或写入消息,从而实现广播或单播通信模式。
(1)解耦
允许你独立的扩展或修改两边的处理过程,只要确保它们遵守|同样的接口约束。(2)冗余
消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。
(3)扩展性
因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。
(4)灵活性&峰值处理能力
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
(5)可恢复性
系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。(6)顺序保证:
在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。(Kafka保证一个Partition内的消息的有序性
(7)缓冲
有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。
(8)异步通信
很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
Kafka是一种高吞吐量的分布式发布/订阅消息系统,这是官方对kafka的定义,这样说起来,可能不太好理解,这里简单举个例子:现在是个大数据时代,各种商业、社交、搜索、浏览都会产生大量的数据。那么如何快速收集这些数据,如何实时的分析这些数据,是一个必须要解决的问题,同时,这也形成了一个业务需求模型,即生产者生产(produce)各种数据,消费者(consume)消费(分析、处理)这些数据。那么面对这些需求,如何高效、稳定的完成数据的生产和消费呢?这就需要在生产者与消费者之间,建立一个通信的梁,这个桥梁就是消息系统。从微观层面来说,这种业务需求也可理解为不同的系统之间如何传递消息。
kafka的一些核心概念和角色
> Broker:Kafka集群包含一个或多个服务器,每个服务器被称为broker(经纪人)。
> Topic:每条发布到Kafka集群的消息都有一个分类,这个类别被称为Topic(主题)。
> Producer:指消息的生产者,负责发布消息到kafkabroker
> Consumer:指消息的消费者,从kafkabroker拉取数据,主消费这些已发布的消息。
> Partition:Partition是物理上的概念,每个Topic包含一个或多个Partition,每个partition都是一个有序的队列。partition中的每条消消息都会被分配一个有序的id(offset)。
> ConsumerGroup:消费者组,可以给每个Consumer指定消费组,若不指定消费者组,则属于默认的group。
> Message:消息,通信的基本单位,每个producer可以向一个topic发布一些消息。
一个典型的Kafka集群包含若干Producer,若干broker、若干(Consumer Group以及一个Zookeeper集群。Kafka通过Zookeeper管理集群配置,选举leader,以及在ConsumerGroup发生变化时进行rebalance。Producer使用push模式将消息发布到broker,Consumer使用pull模式从broker订阅并消费消息。
kafka支持消息持久化存储,持久化数据保存在kafka的日志文件中,在生产者生产消息后,kafka不会直接把消息传递给消费者,而而是先要在broker中进行存储,为了减少磁盘写入的次数,broker会将消息暂时缓存起来,当消息的个数或尺寸、大小达到一定阀值时,再统一写到磁盘上,这样不但提高了kafka的执行效率,也减少了磁盘I0调用次数。
Kafka中的topic(主题)是以partition的形式存放的,每一个topic都可以设置它的partition数量,Partition的数量决定了组成topic的log的数量。推荐partition的数量一定要大于同时运行的consumer的数量。另外,建议partition的数量要小于等于集群broker的数量,这样消息数据就可以均匀的分布在各个broker中
Producer是消息和数据的生产者,它发送消息到broker时,会根据Paritition机制选择将其存储到哪一个Partition。女日果Partition机制设置的合理,所有消息都可以均匀分布到不同的Partition里,这样就实现了数据的负载均衡。如果一个Topic对应一个文件,那这个文件所在的机器I/0将会成为这个Topic的性能瓶颈,而有了Partition后,不同的消息可以并行写入不同broker的不同Partition里,极大的提高了吞吐率。
Kafka发布消息通常有两种模式:队列模式(queuing)和发布/订阅模式(publish-subscribe)。在队列模式下,只有一个消费组,而这个消费组有多个消费者,一条消息只能被这个消费组中的一个消费者所消费;而在发布/订阅模式下,可有多个消费组,每个消费组只有一个消费者,同一条消息可被多个消费组消费。
Kafka中的Producer和consumer采用的是push、pull的模式,即producer向broker进行push消息,comsumer从bork进行pull消息,push和pull对于消息的生产和消费是异步进行的。pull模式的一个好处是consumer可自主控制消费消息的速率,同时consumer还可以自己控制消费消!息的方式是批量的从broker拉取数据还是逐条消费数据。
Zookeeper是一种分布式协调技术,所谓分布式协调技术主要是用来解决分布式环境当中多个进程之间的同步控制,让他们有序的去访问某种共享资源,防止造成资源竞争(脑裂)的后果。脑裂是指在主备切换时,由于切换不彻底或其他原因,导致客户端和Slave误以为出现两个activemaster,最终使得整个集群处于混乱状态
Zookeeper是一种为分布式应用所设计的高可用、高性能的开源协调服务,它提供了一项基本服务:分布式锁服务,同时,也提供了数据的维护和管理机制,如:统一命名服务、状态同步服务、集群管理、分布式消息队列、分布式应用配置项的管理等等。
(1)什么是单点故障问题呢?
所谓单点故障,就是在一个主从的分布式系统中,主节点负责任务调度分发,从节点负责任务的处理,而当主节点发生故障时,整个应用多系统也就瘫痪了,那么这种故障就称为单点故障。那我们的解决方法就是通过对集群master角色的选取,来解决分布式系统单点故障的问题。
(2)传统的方式是怎么解决单点故障的?以及有哪些缺点听呢?
传统的方式是采用一个备用节点,这个备用节点定期向主节点发送ping包主节点收到ping包以后向备用节点发送回复Ack信息,当备用节点收到回复的时候就会认为当前主节点运行正常,让它继续提供服务。而兰当主节点故障时,备用节点就无法收到回复信息了,此时,备用节点就认为主节点宕机,然后接替它成为新的主节点继续提供服务。这种传统解决单点故障的方法,虽然在一定程度上解决了问题,但是有一个隐患,就是网络问题,可能会存在这样一种情况:主节点并没有有出现故障,只是在回复ack响应的时候网络发生了故障,这样备用节点就无法中收到回复,那么它就会认为主节点出现了故障,接着,备用节点将接管主节点的服务,并成为新的主节点,此时,分布式系统中就出现了两个主节点(双Master节点)的情况,双Master节点的出现,会导致分布式系统的服务发生混乱。这样的话,整个分布式系统将变得不可用。为了防止出现这种情况,就需要引入2ookeeper来解决这种问题。
下面通过三种情形来讲解:
(1)master启动
在分布式系统中引入Zookeeper以后,就可以配置多个主节点,这里以配置两个主节点为例,假定它们是主节点A和主节点B,当两个主节点都启动后,它们都会向ZooKeeper中注册节点信息。我们假设主节点A注册的节点信息是master00001,主节点B注册的节点信息是master00002,注册完以后会进行选举,选举有多种算法,这里以编号最小作为选举算法为例,编号最小的节点将在选举中获胜并获得锁成为主节点,也就是主节点A将会获得锁成为主节点,然后主节点B将被阻塞成为一个备用节点。这样,通过这种方式Zookeeper就完成了对两个Master进程的调度。完成了主、备节点的分记和协作。(2)master故障
如果主节点A发生了故障,这时候它在ZooKeeper所注册的节点信息会被自动删除,而ZooKeeper会自动感知节点的变化,发现主节点A故障后,会再次发出选举,这时候主节点B将在选举中获胜,替代主节点A后成为新的主节点这样就完成了主、被节点的重新选举。
(3)master恢复
如果主节点恢复了,它会再次向ZooKeeper注册自身的节点信息,只不过这时候它注册的节点信息将会变成master00003,而不是原来的信息。ZooKeeper会感知节点的变化再次发动选举,这时候,主节点B在选举中会再次获胜继续担任主节点,主节点A会担任备用节点。
zookeeper就是通过这样的协调、调度机制如此反复的对集群进行管理和状态同步的。
zookeeper集群主要角色有server和client,其中server又分为1eaderfollower和observer三个角色,每个角色的含义如下:
Leader:领导者角色,主要负责投票的发起和决议,以及更新系统状态。
follower:跟随着角色,用于接收客户端的请求并返回结果合客户端,在选举过程中参与投票。observer:观察者角色,用户接收客户端的请求,并将写请求转发给1eader,同时同步leader状态,但是不参与投票。0bserver目的是扩展系统,提高伸缩性。
client:客户端角色,用于向zookeeper发起请求。
Zookeeper修改数据的流程:Zookeeper集群中每个Server在内存中存储了一份数据,在Zookeeper启动时,将从实例中选举一个Server作为leader,Leader负责处理数据更新等操作,当且仅当大多数Server在内存学中成功修改数据,才认为数据修改成功。
Zookeeper写的流程为:客户端Client首先和一个Server!或者 Observe通信,发起写请求,然后Server将写请求转发给Leader,Leader再将写请求转发给其它Server,其它Server在接收到写请求后写入数据并响应Leader,Leader在接收到大多数写成功回应后,认为数据写成功,最后响应应Client,完成一次
写操作过程。
Broker是分布式部署并且相互之间相互独立,但是需要有一个注册系统能够将整个集群中的Broker管理起来,此时就使用到了Zookeeper。在Zookeeper 上会有一个专门用来进行Broker服务器列表记录的节点:/brokers/ids
每个Broker在启动时,都会到Zookeeper上进行注册,即到/brokers/ids下创建属于自己的节点,如/brokers/ids/[0...N]。
Kafka使用了全局唯一的数字来指代每个Broker服务器,不同同的Broker必须使用不同的BrokerID进行注册,创建完节点后,每个Broker就会将自己的IP地址和端口信息记录到该节点中去。其中,Broker创建的的节点类型是临时节点,一旦Broker岩机,则对应的临时节点也会被自动删除。
在Kafka中,同一个Topic的消息会被分成多个分区并将其分布在多个Broker上,这些分区信息及与Broker的对应关系也都是由Zookeeper在维护,由专门的节点来记录,如:/borkers/topics
Kafka中每个Topic都会以/brokers/topics/[topic]的形式被记录,如/brokers/topics/login和/brokers/topics/search等。Broker服务器启动后,会到对应Topic节点(/brokers/topics)上注册自己的BrokerID并写入针对该Topic的分区总数,如/brokers/topics/login/3->2,这个节点表示Broker ID为3的一个Broker服务器,对于"login"这个Topic的消息,提是供了2个分区进行消息存储,同样,这个分区节点也是临时节点。
由于同一个Topic消息会被分区并将其分布在多个Broker」,因此,生产者需要将消息合理地发送到这些分布式的Broker上,那么如何实现生产者的负载均衡,Kafka支持传统的四层负载均衡,也支持Zookeeper方式实现负载均衡
(1)四层负载均衡
根据生产者的IP地址和端口来为其确定一个相关联的Broker。通常,一个生产者只会对应单个Broker,然后该生产者产生的消息都发往该该Broker。这种方式逻辑简单,每个生产者不需要同其他系统建立额外的TCP连接,只需要和Broker维护单个TCP连接即可。但是,其无法做到真正的负载均衡,因为实际系统中的每个生产者产生的消息量及每个Broker的消息存储量都是不不一样的,如果有些生产者产生的消息远多于其他生产者的话,那么会导致不同的Broker接收到的消息总数差异巨大,同时,生产者也无法实时感知到Broker的新增和删除。
(2)使用Zookeeper进行负载均衡
由于每个Broker启动时,都会完成Broker注册过程,生产者会通过该节点的变化来动态地感知到Broker服务器列表的变更,这样就可以实现动态的负载均衡机制。
与生产者类似,Kafka中的消费者同样需要进行负载均衡来实现多个消费者合理地从对应的Broker服务器上接收消息,每个消费者分组包含若干消费者,每条消息都只会发送给分组中的一个消费者,不同的消费者分组消费自己特定的Topic下面的消息,互不干扰。
只识而无法治必要求生活动工艺术为你们的长情人间失望还是为惠王不宜思议于疫情防控措施落实力消费组(ConsumerGroup)下有多个Consumer(消费者)。对于每个消费者组(Consumer Group),Kafka都会为其分配一个全局唯一的Group ID,Group内部的所有消费者共享该ID。订阅的topic下的每个分区只能分配给某个group 下的一个consumer
(当然该分区还可以被分配给其他group)。同时,Kafka为每个消费者分配一个ConsumerID,通常采用"Fdostname: UUID形式表示。
在消费者对指定消息分区进行消息消费的过程中,需要定时地将分区消息的消费进度0ffset记录到Zookeeper上,以便在该消费者进行重启或者其他消费者重新接管该消息分区的消息消费后,能够从之前的进度开始继续进行行消息消费0ffset在Zookeeper中由一个专门节点进行记录,其节点路径为:/consumers/[group_id]/offsets/[topic]/[broker_id-partitionid]节点内容就是0ffset的值。
消费者服务器在初始化启动时加入消费者分组的步骤如下:
(1)注册到消费者分组
每个消费者服务器启动时,都会到Zookeeper的指定节点下创建一个属于自己的消费者节点,例如/consumers/[group_id]/ids/[consumer_id],完成节点创建后,消费者就会将自己订阅的Topic信息写入该临时节点。
(2)对消费者分组中的消费者的变化注册监听
每个消费者都需要关注所属消费者分组中其他消费者服务器的变化情况,即对/consumers/[group_id]/ids 节点注册子节点变化的Watcher]监听,一旦发现消费者新增或减少,就触发消费者的负载均衡。
(3)对Broker服务器变化注册监听
消费者需要对/broker/ids/[0-N]中的节点进行监听,如果发现Broker服务器列表发生变化,那么就根据具体情况来决定是否需要进行消费者负载均衡。
(4)进行消费者负载均衡
为了让同一个Topic下不同分区的消息尽量均衡地被多个消费者消费而进行消费者与消息分区分配的过程,通常,对于一个消费者分组,如果组内的消费者服务器发生变更或Broker服务器发生变更,会发出消费者负载均衡。
更改主机名并添加地址映射
[root@localhost~]#hostnamectl set-hostname kafkal
[root@kafkal~]#echo '192.168.10.101 kafkal' >> /etc/hosts
Zookeeper运行依赖java环境,需要先安装 java,后安装zookeeper
[root@kafkal ~]#yum -y install java
[root@kafkal ~]#tar zxvf apache-zookeeper-3.6.0-bin. tar.g2
[root@kafkal ~]#mv apache-zookeeper-3.6.0-bin /etc/zookeeper
[root@kafkal ~]#cd /etc/zookeeper/conf
[root@kafkal conf]#my zoo_sample.cfg zoo.cfg
编辑zookeeper配置文件
[root@kafkal conf]#vi zoo.cfg
dataDir=/etc/zookeeper/zookeeper-data
启动并验证zookeeper
[root@kafkal conf]#cd /etc/zookeeper/
[root@kafkal zookeeper]#mkdir zookeeper-data
[root@kafkal zookeeper]# ./bin/zkServer.sh start
[root@kafkal zookeeper]# ./bin/zkServer.sh status
[root@kafkal ~]#tar zxvf_kafka_2.13-2.4.1.tgz
[root@kafkal ~]#mv kafka_2.13-2.4.1 /etc/kafka
[root@kafkal ~]#cd /etc/kafka/
修改kafka配置文件
[root@kafkal kafka]#vi config/server.properties
log.dirs=/etc/kafka/kafka-logs #60行
启动kafka
[root@kafkal kafka]#mkdir /etc/kafka/kafka-logs
[root@kafkal kafka]#nohup bin/kafka-server-start. shconfig/server. pro perties &
检查两个端口的开启状态
[root@kafkal kafka]#netstat -anpt | grep 2181
[root@kafkal kafka]#netstat -anpt | grep 9092
注意:启动时先启动zookeeper,关闭时先关闭kafka
如果要关闭zookeeper
[root@kafkal zookeeper]# /etc/zookeeper/bin/zkServer. sh stop
如果要关闭kafka
[root@kafkal kafka]## /etc/kafka/bin/kafka-server-stop. sh
如果关不了,就kill杀死该进程
修改脚本(因脚本中会提示大量egrep已经过时警告)
[root@kafkal kafka]#sed -i's/egrep/grep -E\' bin/kafka-run-class. sh
创建topic
[root@kafkal kafka]#bin/kafka-topics. sh --create --zookeeper kafka1:2
181 --replication-factor 1 --partitions 1 --topictest
列出topic
[root@kafkal kafka]#bin/kafka-topics. sh --list --zookeeeper kafka1:2181
查看topic
[root@kafkal kafka]#bin/kafka-topics. sh --describe --zoopkeeper kafkal:2181 --topic test
生产消息
[root@kafkal kafka]#bin/kafka-console-producer. sh --broker-list kafka1:9092 --topic test
消费消息(打开另一个终端,一边生产消息,一边查看消费消息)
[root@kafkal kafka]#bin/kafka-console-consumer. sh --bootstrap-server kafkal:9092 --topic test
删除 topic
[root@kafkal kafka]#bin/kafka-topics.sh --delete --zookeeper kafkal:2181 --topic test
操作系统 | 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 |
关闭防火墙和selinux
[root@localhost~]#systemctl stop firewalld
[root@localhost~]# setenforce 0
修改主机名
kafkal
[root@localhost~]#hostnamectl set-hostname kafkal
Kafka2
[root@localhost~]#hostnamectl set-hostname kafka2
Kafka3
[root@localhost~]#hostnamectl set-hostname kafka3
添加地址映射(三个节点都要做)
cat > /etc/hosts << EOF
192.168.10.101 kafkal
192.168.10.102kafka2
192.168.10.103kafka3
EOF
3个节点都要操作,下面以kafkal主机为例
安装zookeeper
[root@kafkal ^]yum -y install java
[root@kafkal ^]tar zxvf apache-zookeeper-3.6.0-bin. targ2
[root@kafkal^]mv apache-zookeeper-3.6.0-bin /etc/zookeeper
[root@kafkal ~]cd /etc/zookeeper/conf
[root@kafkal conf]mv zoo_sample.cfg zoo.cfg
编辑配置文件
[root@kafkal conf]vi zoo.cfg
dataDir=/etc/zookeeper/zookeeper-data
clientPort=2181
server.1=192.168.10.101:2888:3888:3888
server.2=192.168.10.102:2888:3888:3888
server.3=192.168.10.103:2888:3888:3888
注释:zookeeper只用的端口
2181:对cline端提供服务
3888:选举leader使用
2888: 黄苷卢鑫达快用(Leader 蓝系此端口)
新增数据目录
[root@kafkal conf]cd /etc/zookeeper/
[root@kafkal conf]mkdir zookeeper-data
创建ID节点
节点1:
[root@kafkal conf]#echo 'l'>/etc/zookeeper/zookeeper-data/myid
节点2:
[root@kafka2 conf]#echo '2' > /etc/zookeeper/zookeeper-data/myid
节点3:
[root@kafka3 conf]#echo '3' > /etc/zookeeper/zookeeper-data/myid
安装Kafka
3个节点都要操作,下面以kafkal主机为例
[root@kafkal~]tar zxvf kafka_2.13-2.4.1.tgz
[root@kafkal~]mv kafka_2.13-2.4.1 /etc/kafka
配置kafka配置文件
[root@kafkal ~]cd /etc/kafka/
[root@kafkal kafka]vi config/server.properties
broker.id=l
##21行修改,注意其他两个的id分别是2和3
listeners=PLAINTEXT://192.168.207.131:9092
#31行修改,其他节点改成各自的IP地址
log.dirs=/etc/kafka/kafka-logs
## 60行 修改
num.partitions=l
##65行分片数量,不能超过节点数
zookeeper. connect=192. 168. 10. 101 :2181, 192.168.10.102:2181, 192.168.10.103:2181
##123行,填写集群中各节点的地址和端口
注释:
9092是kafka的监听端口
启动kafka服务
[root@kafkal kafka]mkdir /etc/kafka/kafka-logs
[root@kafkal kafka]nohup ./bin/kafka-server-start.sh config/server.pr operties &
#如果启动不了,可以将/etc/kafka/kafka-logs中的数据清除再试试
修改脚本(因脚本中会提示大量egrep已经过时警告)
[root@kafkal kafka]sed -i's/egrep/grep -E\' bin/kafka-run-class.sh
创建topic(任意一个节点)
[root@kafkal kafka]bin/kafka-topics. sh --create --zookeeperkafkal :2181
--replication-factor 1 --partitions 1 --topic teest
列出topic(任意一个节点)
[root@kafkal kafka]bin/kafka-topics. sh --list --zookeeper kafkal:2181
[root@kafkal kafka]bin/kafka-topics. sh --list --zookeeper kafka2:2181
[root@kafkal kafka]bin/kafka-topics. sh --list --zookeeper kafka3:2181
生产消息
[root@kafkal
kafka]bin/kafka-console-producer.sh --broker-listkafkal:9092 -topic test
消费消息
[root@kafkal kafka]bin/kafka-console-consumer. sh--bootstrap-server kafkal:9092 --topic test
删除 topic
[root@kafkal kafka]bin/kafka-topics. sh --delete --zookeeper kafka1 :2181 --topic test