今日大纲
- Kafka简介
- Kafka分布式集群安装
- Kafka-topic操作
- Kafka-api
- Kafka和Flume整合案例
- Kafka架构之道
- Kafka Leader Election
- Kafka高性能之道
1. Kafka简介
1.1. 消息队列
1.1.1. 为甚要有消息队列
1.1.2. 消息队列
- 消息 Message
网络中的两台计算机或者两个通讯设备之间传递的数据。例如说:文本、音乐、视频等内容。 - 队列 Queue
一种特殊的线性表(数据元素首尾相接),特殊之处在于只允许在首部删除元素和在尾部追加元素。入队、出队。 - 消息队列 MQ
消息+队列,保存消息的队列。消息的传输过程中的容器;主要提供生产、消费接口供外部调用做数据的存储和获取。
1.1.3. 消息队列的分类
MQ主要分为两类:点对点(p2p)、发布订阅(Pub/Sub)
-
Peer-to-Peer
一般基于Pull或者Polling接收数据
发送到队列中的消息被一个而且仅仅一个接收者所接受,即使有多个接收者在同一个队列中侦听同一消息
即支持异步“即发即收”的消息传递方式,也支持同步请求/应答传送方式[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AC5OkIcq-1584667570107)(E:/%E5%A4%A7%E6%95%B0%E6%8D%AE/spark/kafka1/%E6%96%87%E6%A1%A3/assets/1568684012083.png)]
-
发布订阅
发布到同一个主题的消息,可被多个订阅者所接收
发布/订阅即可基于Push消费数据,也可基于Pull或者Polling消费数据
解耦能力比P2P模型更强[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rba5lfGV-1584667570117)(E:/%E5%A4%A7%E6%95%B0%E6%8D%AE/spark/kafka1/%E6%96%87%E6%A1%A3/assets/1568684181173.png)]
1.1.4. p2p和发布订阅MQ的比较
- 共同点:
消息生产者生产消息发送到queue中,然后消息消费者从queue中读取并且消费消息。 - 不同点:
p2p模型包括:消息队列(Queue)、发送者(Sender)、接收者(Receiver)
一个生产者生产的消息只有一个消费者(Consumer)(即一旦被消费,消息就不在消息队列中)。比如说打电话。
pub/Sub包含:消息队列(Queue)、主题(Topic)、发布者(Publisher)、订阅者(Subscriber)
每个消息可以有多个消费者,彼此互不影响。比如我发布一个微博:关注我的人都能够看到。
1.1.5. 消息系统的使用场景
- 解耦 各系统之间通过消息系统这个统一的接口交换数据,无须了解彼此的存在
- 冗余 部分消息系统具有消息持久化能力,可规避消息处理前丢失的风险
- 扩展 消息系统是统一的数据接口,各系统可独立扩展
- 峰值处理能力 消息系统可顶住峰值流量,业务系统可根据处理能力从消息系统中获取并处理对应量的请求
- 可恢复性 系统中部分键失效并不会影响整个系统,它恢复会仍然可从消息系统中获取并处理数据
- 异步通信 在不需要立即处理请求的场景下,可以将请求放入消息系统,合适的时候再处理
1.1.6. 常见的消息系统
- RabbitMQ Erlang编写,支持多协议AMQP,XMPP,SMTP,STOMP。支持负载均衡、数据持久化。同时支持Peer-to-Peer和发布/订阅模式。
- Redis 基于Key-Value对的NoSQL数据库,同时支持MQ功能,可做轻量级队列服务使用。就入队操作而言,Redis对短消息(小于10kb)的性能比RabbitMQ好,长消息性能比RabbitMQ差。
- ZeroMQ 轻量级,不需要单独的消息服务器或中间件,应用程序本身扮演该角色,Peer-to-Peer。它实质上是一个库,需要开发人员自己组合多种技术,使用复杂度高。
- ActiveMQ JMS实现,Peer-to-Peer,支持持久化、XA(分布式)事务
- Kafka/Jafka 高性能跨语言的分布式发布/订阅消息系统,数据持久化,全分布式,同时支持在线和离线处理
- MetaQ/RocketMQ 纯Java实现,发布/订阅消息系统,支持本地事务和XA分布式事务
1.2. Kafka简介
1.2.1. 简介
Kafka是分布式的发布—订阅消息系统。它最初由LinkedIn(领英)公司发布,使用Scala语言编写,与2010年12月份开源,成为Apache的顶级项目。Kafka是一个高吞吐量的、持久性的、分布式发布订阅消息系统。它主要用于处理活跃live的数据(登录、浏览、点击、分享、喜欢等用户行为产生的数据)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0GmDrs18-1584667570120)(assets/kafka-apis.png)]
三大特点:
- 高吞吐量
可以满足每秒百万级别消息的生产和消费——生产消费。 - 持久性
有一套完善的消息存储机制,确保数据的高效安全的持久化——中间存储。 - 分布式
基于分布式的扩展和容错机制;Kafka的数据都会复制到几台服务器上。当某一台故障失效时,生产者和消费者转而使用其它的机器——整体 - 健壮性。
1.2.2. 设计目标
- 高吞吐率 在廉价的商用机器上单机可支持每秒100万条消息的读写
- 消息持久化 所有消息均被持久化到磁盘,无消息丢失,支持消息重放
- 完全分布式 Producer,Broker,Consumer均支持水平扩展
- 同时适应在线流处理和离线批处理
1.2.3. kafka核心的概念
一个MQ需要哪些部分?生产、消费、消息类别、存储等等。
对于kafka而言,kafka服务就像是一个大的水池。不断的生产、存储、消费着各种类别的消息。那么kafka由何组成呢?
Kafka服务:
- Topic:主题,Kafka处理的消息的不同分类。
- Broker:消息服务器代理,Kafka集群中的一个kafka服务节点称为一个broker,主要存储消息数据。存在硬盘中。每个topic都是有分区的。
- Partition:Topic物理上的分组,一个topic在broker中被分为1个或者多个partition,分区在创建topic的时候指定。
- Message:消息,是通信的基本单位,每个消息都属于一个partition
Kafka服务相关
- Producer:消息和数据的生产者,向Kafka的一个topic发布消息。
- Consumer:消息和数据的消费者,定于topic并处理其发布的消息。
- Zookeeper:协调kafka的正常运行。
2. kafka的分布式安装
2.1. 版本下载
安装包:http://archive.apache.org/dist/kafka/1.1.1/kafka_2.12-1.1.1.tgz
源码包:http://archive.apache.org/dist/kafka/1.1.1/kafka-1.1.1-src.tgz
2.2. 安装过程
- 解压
[bigdata@bigdata01 app]$ tar -zxvf ~/soft/kafka_2.11-1.1.1.tgz -C app/
- 重命名
[bigdata@bigdata01 app]$ mv kafka_2.11-1.1.1/ kafka
- 添加环境变量
[bigdata@bigdata01 kafka]$ vim ~/.bash_profile
export KAFKA_HOME=/home/bigdata/app/kafka
export PATH=$PATH:$KAFKA_HOME/bin
[bigdata@bigdata01 kafka]$ source ~/.bash_profile
- 配置
修改$KAFKA_HOME/config/server.properties
broker.id=11 ## 当前kafka实例的id,必须为整数,一个集群中不可重复
log.dirs=/home/bigdata/data/kafka ## 生产到kafka中的数据存储的目录,目录需要手动创建
zookeeper.connect=bigdata01:2181,bigdata02:2181,bigdata03:2181/kafka ## kafka数据在zk中的存储目录
- 同步到其它机器
scp -r kafka/ hadoop@hadoop02:/home/hadoop/app/
scp -r kafka/ bigdata@bigdata03:/home/hadoop/app/
- 修改配置文件中的broker.id
broker.id=12 ##bigdata02
broker.id=13 ##bigdata03
- 创建数据目录
mkdir -p /home/bigdata/data/kafka
- 启动kafka服务
~/app/kafka/bin/kafka-server-start.sh -daemon ~/app/kafka/config/server.properties
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3rxE49Jf-1584667570122)(assets/1564974407794.png)]
-
kafka服务测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-enHaYrvT-1584667570123)(E:/%E5%A4%A7%E6%95%B0%E6%8D%AE/spark/kafka1/%E6%96%87%E6%A1%A3/assets/1564974489574.png)]
只要我们配置的kafka的服务都在zookeeper中进行了注册,便说明kafka已经安装启动成功
2.3. kafka在zookeeper中的目录说明
/kafka
/cluster
/id {"version":"1","id":"Pks8sWZUT6GBJHqyVGQ5OA"} ---》代表的是一个kafka集群包含集群的版本,和集群的id
/controller {"version":1,"brokerid":11,"timestamp":"1564976668049"} -->controller是kafka中非常重要的一个角色,意为控制器,控制partition的leader选举,topic的crud操作。brokerid意为由其id对应的broker承担controller的角色。
/controller_epoch 2 代表的是controller的纪元,换句话说是代表controller的更迭,每当controller的brokerid更换一次,controller_epoch就+1.
/brokers
/ids [11, 12, 13] --->存放当前kafka的broker实例列表
/topics [hadoop, __consumer_offsets] ---->当前kafka中的topic列表
/seqid 系统的序列id
/consumers --->老版本用于存储kafka消费者的信息,主要保存对应的offset,新版本中基本不用,此时用户的消费信息,保存在一个系统的topic中:__consumer_offsets
/config --->存放配置信息
3. Kafka的基本操作
3.1. kafka的topic的操作
topic是kafka非常重要的核心概念,是用来存储各种类型的数据的,所以最基本的就需要学会如何在kafka中创建、修改、删除的topic,以及如何向topic生产消费数据。
关于topic的操作脚本:kafka-topics.sh
- 创建topic
[bigdata@bigdata01 kafka]$ bin/kafka-topics.sh --create \
--topic hadoop \ ## 指定要创建的topic的名称
--zookeeper
hadoop01:2181,hadoop02:2181,hadoop03:2181/kafka \ ##指定kafka关联的zk地址
--partitions 3 \ ##指定该topic的分区个数
--replication-factor 3 ##指定副本因子
bin/kafka-topics.sh --create --topic hadoop --zookeeper hadoop01:2181/kafka --partitions 3 --replication-factor 3
注意:指定副本因子的时候,不能大于broker实例个数,否则报错:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SWRQALVN-1584667570125)(assets/1564976012893.png)]
zookeeper目录变化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pgu7sQFi-1584667570127)(assets/1564976107745.png)]
kafka数据目录的变化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BCUkzhgu-1584667570130)(assets/1564976163903.png)]
- 查看topic的列表
[bigdata@bigdata01 kafka]$ bin/kafka-topics.sh --list \
--zookeeper bigdata01:2181,bigdata02:2181,bigdata03:2181/kafka
hadoop
- 查看每一个topic的信息
[bigdata@bigdata01 kafka]$ bin/kafka-topics.sh --describe --topic hadoop \
--zookeeper bigdata01:2181,bigdata02:2181,bigdata03:2181/kafka
Topic:hadoop PartitionCount:3 ReplicationFactor:3 Configs:
Topic: hadoop Partition: 0 Leader: 12 Replicas: 12,13,11 Isr: 12,13,11
Topic: hadoop Partition: 1 Leader: 13 Replicas: 13,11,12 Isr: 13,11,12
Topic: hadoop Partition: 2 Leader: 11 Replicas: 11,12,13 Isr: 11,12,13
Partition: 当前topic对应的分区编号
Replicas : 副本因子,当前kafka对应的partition所在的broker实例的broker.id的列表
Leader : 该partition的所有副本中的leader领导者,处理所有kafka该partition读写请求
ISR : 该partition的存活的副本对应的broker实例的broker.id的列表
- 修改一个topic
[bigdata@bigdata01 kafka]$ bin/kafka-topics.sh --alter --topic hadoop --partitions 4 --zookeeper bigdata01:2181/kafka
WARNING: If partitions are increased for a topic that has a key, the partition logic or ordering of the messages will be affected
Adding partitions succeeded!
但是注意:partition个数,只能增加,不能减少:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ptthEQf6-1584667570132)(assets/1564976954334.png)]
- 删除一个topic
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ltfsUVww-1584667570133)(assets/1564977032114.png)]
- 生产数据
[bigdata@bigdata01 kafka]$ bin/kafka-console-producer.sh \
--topic hadoop \ -->指定数据被生产的topic
--broker-list bigdata01:9092,bigdata02:9092,bigdata03:9092 --->指定kafka的broker列表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sWE5hAU8-1584667570137)(assets/1564977283073.png)]
- 消费数据
[bigdata@bigdata03 kafka]$ bin/kafka-console-consumer.sh \
--topic hadoop \
--bootstrap-server bigdata01:9092,bigdata02:9092,bigdata03:9092
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L8weFDuH-1584667570137)(assets/1564977398804.png)]
没数据,原因在于消费者后于生产者启动,在消费者启动之前生产者消费的数据变不能直接获取。
如果想要获取消费者启动之前生产者生产的数据,可以添加一个参数–from-beginning。
如图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mrG4eMdn-1584667570138)(assets/1564977543576.png)]
3.2. Kafka的数据消费的总结
kafka消费者在消费数据的时候,都是分组别的。不同组的消费不受影响,相同组内的消费,需要注意,如果partition有3个,消费者有3个,那么便是每一个消费者消费其中一个partition对应的数据;如果有2个消费者,此时一个消费者消费其中一个partition数据,另一个消费者消费2个partition的数据。如果有超过3个的消费者,同一时间只能最多有3个消费者能消费得到数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XO49m37e-1584667570139)(assets/consumer-groups.png)]
bin/kafka-console-consumer.sh --topic spark \
--bootstrap-server bigdata01:9092,bigdata02:9092,bigdata03:9092 \
--group haha \ ---》消费者对应的消费者组
--offset earliest \ --->从什么位置(消息的偏移量)开始消费
--partition 2 ---->消费哪一个分区中的数据
offset:是kafka的topic中的partition中的每一条消息的标识,如何区分该条消息在kafka对应的partition的位置,就是用该偏移量。offset的数据类型是Long,8个字节长度。offset在分区内是有序的,分区间是不一定有序。如果想要kafka中的数据全局有序,就只能让partition个数为1。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Hi3lmql-1584667570140)(assets/log_anatomy.png)]
在组内,kafka的topic的partition个数,代表了kafka的topic的并行度,同一时间最多可以有多个线程来消费topic的数据,所以如果要想提高kafka的topic的消费能力,应该增大partition的个数。
3.3. kafka的编程的api
3.3.1. 创建kafka的项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MoRjIpnD-1584667570142)(assets/1564987565272.png)]
指定maven坐标
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MvmWIFw3-1584667570148)(assets/1564987594037.png)]
指定存放目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eRnbq0yq-1584667570149)(assets/1564987640236.png)]
导入maven依赖
<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>1.1.1</version>
</dependency>
<!-- 下面的依赖,包含了上面的kafka-clients,所以只需要引入下面即可 -->
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka_2.11</artifactId>
<version>1.1.1</version>
</dependency>
3.3.2. kafka生产者的api操作
入口类:Producer
- 入门案例
public class MyKafkaProducer {
public static void main(String[] args) throws IOException {
/*
K: --->代表的是向topic中发送的每一条消息的key的类型,key可以为null
V: --->代表的是向topic中发送的每一条消息的value的类型
*/
Properties properties = new Properties();
// properties.put("bootstrap.servers", "bigdata01:9092,bigdata02:9092,bigdata03:9092");
properties.load(MyKafkaProducer.class.getClassLoader().getResourceAsStream("producer.properties"));
Producer<Integer, String> producer = new KafkaProducer<Integer, String>(properties);
//发送数据
ProducerRecord<Integer, String> record = new ProducerRecord("spark", "11111");
producer.send(record);
producer.close();
}
}
配置:
bootstrap.servers=bigdata01:9092,bigdata02:9092,bigdata03:9092
key.serializer=org.apache.kafka.common.serialization.IntegerSerializer
value.serializer=org.apache.kafka.common.serialization.StringSerializer
- 创建producer时需要指定的配置信息
bootstrap.servers=bigdata01:9092,bigdata02:9092,bigdata03:9092 ## kafka的服务器
key.serializer=org.apache.kafka.common.serialization.IntegerSerializer ##Key的序列化器
value.serializer=org.apache.kafka.common.serialization.StringSerializer ##value的序列化器
acks=[0|-1|1|all] ##消息确认机制
0: 不做确认,直管发送消息即可
-1|all: 不仅leader需要将数据写入本地磁盘,并确认,还需要同步的等待其它followers进行确认
1:只需要leader进行消息确认即可,后期follower可以从leader进行同步
batch.size=1024 #每个分区内的用户缓存未发送record记录的空间大小
## 如果缓存区中的数据,没有沾满,也就是任然有未用的空间,那么也会将请求发送出去,为了较少请求次数,我们可以配置linger.ms大于0,
linger.ms=10 ## 不管缓冲区是否被占满,延迟10ms发送request
buffer.memory=10240 #控制的是一个producer中的所有的缓存空间
retries=0 #发送消息失败之后的重试次数
- 修改配置查看生产数据情况
配置文件
bootstrap.servers=bigdata01:9092,bigdata02:9092,bigdata03:9092
# specify the compression codec for all data generated: none, gzip, snappy, lz4
compression.type=none
# name of the partitioner class for partitioning events; default partition spreads data randomly
# 输入进入分区的方式
#partitioner.class=
# the maximum amount of time the client will wait for the response of a request
# 请求超时时间
#request.timeout.ms=
# how long `KafkaProducer.send` and `KafkaProducer.partitionsFor` will block for
# 使用send方法最大消息阻塞时间
#max.block.ms=
# the producer will wait for up to the given delay to allow other records to be sent so that the sends can be batched together
linger.ms=5000
# the maximum size of a request in bytes
## 最大的请求大小
#max.request.size=
# the default batch size in bytes when batching multiple records sent to a partition
batch.size=1024
buffer.memory=10240
key.serializer=org.apache.kafka.common.serialization.IntegerSerializer
value.serializer=org.apache.kafka.common.serialization.StringSerializer
代码
public class MyKafkaProducer {
public static void main(String[] args) throws Exception {
/*
K: --->代表的是向topic中发送的每一条消息的key的类型,key可以为null
V: --->代表的是向topic中发送的每一条消息的value的类型
*/
Properties properties =