Kafka 核心原理(贼全面)

一、Kafka 概述

1.1 定义

  Kafka是一个分布式的基于发布/订阅模式消息队列Message Queue),主要应用于大数据实时处理领域,处于大数据数据传输层,属于消息中间件。如AB两个系统需要通信,但并不是直连中间通过消息中间件,还可以实现解耦

1.2 消息队列

1.2.1 传统消息队列的应用场景

在这里插入图片描述

(1)同步处理

  整个线程串行,并不高效

(2)异步处理

   请求数据写入MQ,并返回响应结果,可以做到解耦,等系统上线时去MQ取数据;还可以缓解服务端的压力(削峰)

(3)使用消息队列的好处

1)解耦
  允许独立的拓展或者修改两边的处理过程。只要确保它们遵守同样的接口约束。
2)可恢复性
  系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
3)缓冲
  有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。更多的是解决生产大于消费的问题。
4)灵活性 & 峰值处理能力
  在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
5)异步通信
  很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

1.2.2 消息队列的两种方式

(1)点对点模式

  消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。
在这里插入图片描述
总结:一对一,消费者主动拉去数据,消息收到后消息清除。消息不可复用缺点明显

(2)发布/订阅模式

  消息生产者(发布)将消息发布到 topic 中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到 topic 的消息会被所有订阅者消费。
在这里插入图片描述
总结:一对多,消费者消费数据后不会清除消息,但毕竟是个消息队列不是类似hdfs的文件存储系统,数据不会无限期的保存,一定时间后会被删除。

分析:对于消费者消费数据有两种方式:消息队列推数据给消费者、消费者主动拉去数据。对于这种形式,是由当前队列来决定,下游的消费者可能处理速度不同,例如消费者1消息处理速度为10M/s,消费者2消息处理速度为100M/s,但是消息队列推出消息的速度统一为50M/s,因此消费者1直接崩溃,消费者2造成资源浪费。Kafka是基于第二种,消费者主动拉取数据,因此消费者的消费速度可以由消费者自己决定。但是这种模式也有一个缺点,消费者主动拉取数据一定要做长轮询,如果消息队列长时间没有推送数据也会造成一定的资源浪费。

1.3 Kafka 基础架构

在这里插入图片描述
1)Producer :消息生产者,就是向 kafka broker 发消息的客户端
2)Consumer :消息消费者,向 kafka broker 取消息的客户端
3)Consumer Group (CG):消费者组,由多个 consumer组成。消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者,提高消费能力但一个消费者组理论上不高于一个消息主题的分区个数。
4)Broker :一台 kafka 服务器就是一个 broker。一个集群由多个broker 组成。一个broker可以容纳多个topickafka的多节点使用的zk是同一个集群那么就能组成kafka集群
5)Topic :可以理解为一个队列,生产者和消费者面向的都是一个 topic,作用为分类消息。
6)Partition:为了实现扩展性,一个非常大的 topic可以分布到多个broker(即服务器)上,一个 topic可以分为多个partition,每个 partition 是一个有序的队列
7)Replica:副本,为保证集群中的某个节点发生故障时,该节点上的 partition 数据不丢失,且kafka仍然能够继续工作,kafka 提供了副本机制,一个 topic 的每个分区都有若干个副本,一个 leader 和若干个follower
8)leader:每个分区多个副本的“主”,生产者发送数据的对象,以及消费者消费数据的对象都是leader
9)follower:每个分区多个副本中的“从”,实时从 leader 中同步数据,保持和 leader数据的同步。leader 发生故障时,某个 follower 会成为新的 follower
10)zk:帮助kafka集群存储一些信息;帮助消费者存储消费位置信息。0.9版本后存储在kafka本地(不是本地磁盘)

1.3.1 总结

  首先群起kafka集群,brocker相当于一个节点起的一个kafka进程,消息都是存储在brocker中,如果只有一个brocker存储数据容易乱套,如多个生产者生产数据都要使用kafka会导致消息数据混乱。这时候就需要topic,相当于把许多消息进行分类,消费者按需求去对应的topic取消息数据;同一个主题会在不同的brocker存在,即进行分区,提高某个节点的负载均衡,将来消息数据生产出来,均分给不同节点的相同topic,一定意义上提高了集群的并发和负载能力;同时一个分区topic对应一个leader和一个follower,这个follower相当于备份作用提供集群的高可用(只有在leader挂了才会起作用,正常情况消费者只从leader取数据),因此同一个分区topicleader和一个follower必定是在两个不同的节点上,将来leader所在的节点挂了可以将follower提升为leader继续工作。
  对于消费者有个消费者组概念,可以把多个消费者用一个组名,同时消费者组有一个特点:一个分区只能被一个组的一个消费者消费,大大提高消费能力,但一个消费者组的消费者个数不能大于一个主题的分区数否则会造成资源的浪费,因此理想的并发度是消费者组的消费者个数等于某个主题的分区数。
  对于zk会帮助kafka集群存储一些信息,同时在接下来搭建kafka集群的时候会发现没有所谓hdfsnamenodekafka集群则是靠使用一个集群的zk来组成自己的集群,即只要kafka各个节点使用的zk是同一个集群,那么我就是一个kafka集群。
  对于消费者最重要的是要实现类似断点续传功能,即一个消费者挂掉重启后还可以接着原来的位置继续消费。在0.9版本之前将偏移量offset存储在zk中,但是0.9之后将其存储在kafka中的系统topic中(本地磁盘,默认存储7天)。why?考虑到消费者既要连接kafka消费数据同时要实时的向zk中存储数据,效率低下。

二、Kafka 快速入门

2.1 集群搭建

2.1.1 上传压缩包并解压

tar -zxvf kafka_2.13-2.5.0.tgz

2.13代表scala版本,2.5.0kafka版本

2.1.2 修改配置文件

cd kafka_2.13-2.5.0/config/
# The id of the broker. This must be set to a unique integer for each broker
broker.id=0

# A comma separated list of directories under which to store log files
log.dirs=/usr/local/soft/kafka_2.13-2.5.0/logs

# Zookeeper connection string (see zookeeper docs for details).
# This is a comma separated host:port pairs, each corresponding to a zk
# server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002".
# You can also append an optional chroot string to the urls to specify the
# root directory for all kafka znodes.
zookeeper.connect=master:2181,slave01:2181,slave02:2181

2.1.3 配置环境变量并分发

分发脚本

#!/bin/bash
#1 获取输入参数个数,如果没有参数,直接退出
pcount=$#
if [ $pcount == 0 ]
then
	echo no args
	exit
fi
#2 获取文件名称
p1=$1
fname=`basename $p1`
echo fname=$fname

#3 获取上级目录到绝对路径
pdir=`cd -P $(dirname $p1); pwd`
echo pdir=$pdir

#4 获取当前用户名称
user=`whoami`

rsync -rvl $pdir/$fname $user@slave01:$pdir
rsync -rvl $pdir/$fname $user@slave02:$pdir

2.1.4 编写群起脚本

  kafka没有实现类似hdfsworkers的群起集群功能,需要我们一个个节点启动(类似zk),因此需要自己编写群起脚本

#!/bin/bash
pcount=$#
if [ $pcount == 0 ]
then
	echo "no args"
	exit
fi

case $1 in
"start"){
        echo ""
        echo "—————————————————————————————————————————"
    for i in master slave01 slave02
    do
        echo ""
        echo "    $i start kafka successfully   "
        echo ""
        ssh $i "/usr/local/soft/kafka_2.13-2.5.0/bin/kafka-server-start.sh -daemon /usr/local/soft/kafka_2.13-2.5.0/config/server.properties"
    done
        echo "—————————————————————————————————————————"
        echo ""
};;
"stop"){
        echo ""
        echo "—————————————————————————————————————————"
    for i in master slave01 slave02
    do
        echo ""
        echo "    $i stop kafka successfully     "
        echo ""
        ssh $i "/usr/local/soft/kafka_2.13-2.5.0/bin/kafka-server-stop.sh /usr/local/soft/kafka_2.13-2.5.0/config/server.properties"
    done
        echo "—————————————————————————————————————————"
        echo ""
};;
esac

注意:kafka关闭会有延迟,也就是说关闭后立刻jps可能还能看到kafka进程,稍等一下即可

2.2 Kafka 命令行操作

(1)创建一个主题

kafka-topics.sh --zookeeper master:2181 --create --topic first --partitions 2 --replication-factor 2

  因为kafka集群需要将元数据写入zk中(0.9版本后消费者的数据不写入zk),因此需要连接zk集群同时指定分区数和副本数(副本数有坑,注意和hdfs的副本数区分,一会有shell演示),根据配置文件进入logs文件夹(后面会将日志和消息数据分开),并查看所有节点的logs文件夹。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
first-0 first-1表示分区数,即kafka以主题名和分区数对topic进行命名且以文件夹的形式,纵观三台节点可以发现副本数也是两个。

(2)查看所有的topic

kafka-topics.sh --zookeeper master:2181 --list

(3)查看topic的详细信息

kafka-topics.sh --zookeeper master --describe --topic first

Topic: first    PartitionCount: 2       ReplicationFactor: 2    Configs:
        Topic: first    Partition: 0    Leader: 2       Replicas: 2,0   Isr: 2,0
        Topic: first    Partition: 1    Leader: 0       Replicas: 0,1   Isr: 0,1

  可以看出该topic有2个分区(first-0first-1)和2个副本,其中first-0broker.id为0和2上,且leaderbroker.id为2的分区;first-1broker.id为0和1上,且leaderbroker.id为0的分区,图示如下:在这里插入图片描述

(4)删除topic

kafka-topics.sh --zookeeper master:2181 --delete --topic first

Topic first is marked for deletion.
Note: This will have no impact if delete.topic.enable is not set to true.

在这里插入图片描述
  执行删除的topic不会立刻删除而是被标记一下,随后才会被删除。

(5)浅谈副本数

  在创建topic时需要指定副本数即replication-factor,很容易联想到hdfs的副本数,在hdfs中副本数可以配置任意值即使超过集群数,它的策略是当增加集群数时会自己拷贝副本数知道达到配置的副本数;在kafka并不是这样,当创建的副本数大于可用的broker时会报错,即原先的kafka集群有三个broker此时创建三个副本的topic时不会报错,这时候突然有一个节点宕机原先的topic不受影响但是随后不能再创建三个副本的topic,一句话总结就是:hdfs的副本数是最大副本数,kafka的就是现在的副本数。

kafka-topics.sh -zookeeper master:2181 --partitions 4 --replication-factor 4

Error while executing topic command : Replication factor: 4 larger than available brokers: 3.
[2020-07-30 17:08:06,756] ERROR org.apache.kafka.common.errors.InvalidReplicationFactorException: Replication factor: 4 larger than available brokers: 3.
 (kafka.admin.TopicCommand$)

但是分区不受影响。

kafka-topics.sh -zookeeper master:2181 --create --topic first--partitions 4 --replication-factor 4

查看topic的详细信息

Topic: first    PartitionCount: 4       ReplicationFactor: 3    Configs:
        Topic: first    Partition: 0    Leader: 2       Replicas: 2,0,1 Isr: 2,0,1
        Topic: first    Partition: 1    Leader: 0       Replicas: 0,1,2 Isr: 0,1,2
        Topic: first    Partition: 2    Leader: 1       Replicas: 1,2,0 Isr: 1,2,0
        Topic: first    Partition: 3    Leader: 2       Replicas: 2,1,0 Isr: 2,1,0

(6)日志数据分离

  为了使日志和消息数据分开存储,我们需要将其分离,步骤如下

  1. 关闭kafka集群,删除logs文件夹
  2. 进入zk删除kafka相关[除了自己的东西其他全部删除]
  3. 修改配置文件log.dirs[这个其实是配置数据的地方]
  4. 启动kafka集群
    在这里插入图片描述
    已经实现了日志数据分离的效果,可以通过创建一个topic来验证一下
    在这里插入图片描述

(7)控制台测试生产者、消费者

常用命令都放在kafka/bin中,见名知意可知需要的命令为

kafka-console-consumer.sh
kafka-console-producer.sh
- 生产者测试

生产者直接连接kafka指定主题生产数据,因此代码如下:

kafka-console-producer.sh --bootstrap-server master:9092 --topic first

会进入kafka客户端,等待生产数据

- 消费者测试

上面说过0.9版本消费者的消费记录存储在kafka系统维护的主题(一会就能看到),因此消费者的代码也是一样

kafka-console-consumer.sh --bootstrap-server master:9092 --topic first

窗口会进入阻塞状态等待消费数据,此时可以在生产者那随便生产一点数据观察现象
在这里插入图片描述
kafka是基于订阅/发布模式,且消费者消费数据是拉取模式,因此kafka消息队列即使客户端不在线,当上线时会消费以前的数据(默认消费7天以内),注意:上面的测试代码会读取消费记录,即当重新上线不会重复消费,--from-beginning参数会从头消费。当新建一个消费者会消费离线时发布的数据,同时查看data文件可以发现,分区以一种轮换的方式进行。
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小王是个弟弟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值