kafka

kafka

第一节

分布式流平台

Apache Kafka

1.1 定义
kafka是一个分布式的基于发布/订阅模式的消息队列(message Queue) 分布式*事件流平台*,
可让您跨多台机器读取,写入,存储和处理 [*事件*] 主要应用于大数据实时处理领域(http://kafka.apache.org/documentation/#messages)(在文档中也称为*记录*或 *消息*)。
1.2 流平台具有三个关键功能
- 发布和订阅记录流,类似于消息队列或企业消息传递系统。
- 以容错的持久方式存储记录流。
- 处理发生的记录流。
1.3 Kafka通常用于两大类应用程序
- 建立实时流数据管道,以可靠地在系统或应用程序之间获取数据
- 构建实时流应用程序以转换或响应数据流
1.4 概念
 Kafka是一个分布式系统,由通过高性能[TCP网络协议进行](http://kafka.apache.org/protocol.html)通信的**服务器**和**客户端**组成。它可以部署在内部以及云环境中的裸机硬件,虚拟机和容器上。 

Kafka在一个或多个可以跨越多个数据中心的服务器上作为集群运行。
Kafka集群将*记录*流存储在称为*topic的*类别中。
每个记录由一个键,一个值和一个时间戳组成。
 **服务器**:Kafka作为一台或多台服务器的集群运行,可以跨越多个数据中心或云区域。其中一些服务器构成了存储层,称为代理。其他服务器运行 [Kafka Connect](http://kafka.apache.org/documentation/#connect)来连续导入和导出数据作为事件流,以将Kafka与现有系统集成在一起,例如关系数据库以及其他Kafka群集。为了实现关键任务用例,Kafka群集具有高度的可扩展性和容错能力:如果其任何服务器发生故障,其他服务器将接管其工作,以确保连续运行而不会丢失任何数据。 
1.5 kafka的核心api

Kafka有四个核心的API:

The Producer API 允许一个应用程序发布一串流式的数据到一个或者多个Kafka topic。

The Consumer API 允许一个应用程序订阅一个或多个 topic ,并且对发布给他们的流式数据进行处理。

The Streams API 允许一个应用程序作为一个流处理器,消费一个或者多个topic产生的输入流,然后生产一个输出流到一个或多个topic中去,在输入输出流中进行有效的转换。

The Connector API 允许构建并运行可重用的生产者或者消费者,将Kafka topics连接到已存在的应用程序或者数据系统。比如,连接到一个关系型数据库,捕捉表(table)的所有变更内容。

【官网注意事项】http://kafka.apache.org/quickstart

第二节

模式

2.1 点对点模式

(一对一,消费者主动拉取数据,消息收到后消息清除)

消息生产者生产消息发送到Queue中,然后消费者从Queue中取出并且消费消息。

消息被消费以后,Queue中不再有存储,所以消费着不可能消费到已经被消费的消息。

Queue支持存在多个消费者,但是对一个消息而言,只有一个消费者可以消费。

2.2 发布/订阅模式

( 一对多,消费者消费数据之后不会清除消息)

消息生产者(发布)将消息发布到topic中,同时多个消费者(订阅)消费

该消息,和点对点方式不同,发布到topic的消息会被所有订阅者消费。

第三节

架构

3.1 kafka结构

`1)Produce:消息生产者,就是向kafka broker 发消息的客户端;
不停的往topic队列中
`2)Consumer: 消息管理者,向kafka broker 取消息的客户端;
`3) Consumer Group (CG):消费者组,由多个consumer组成.消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费:消费者组之间互不影响;有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。
`4)Broke: 一台kafka服务器就是一个borker,一个集群由多个broke组成,一个broke可以容纳多个topic.
`5)  Topic: 可以理解为一个队列,生产者和消费者面向的都是一个topic;
           一个topic 是一个队列
6)  Partition:  为了实现扩展性一个非常大的topic可以分不到多个broker(即服务器)上,
    一个topic可以分为多个partition,每个partition 是一个有序的队列;
    一个partition 是副本,副本不会产生在同一台机器上  例如 topic A(broker0  broker 2)
7) Replication: 副本,为保证集群中的某个节点发生故障时,该节点上的partition 数据不丢失
8)  leader: 每个分区多个副本的主,生产者发送数据的对象,以及消费者消费数据的对象都是leader.
9)   follower: 每个分区多个副本中的“从”,实现从leader 中同步数据,保持leader数据的同步,leader 发生故障时,某个follower会成为新的follower。
3.2选举机制

参考链接:

orchome

选举机制原理

kafka leader选举

什么是消费组

1.控制器(Broker)选主     
2.分区多副本选主
3.消费组选主   【简单了解】
控制器选主  
`【优点】: 跟 多分区副本相比 高效,减轻zk负载
`【缺点】: 引入Controller增加了复杂度 需要考虑Controller的Failover

在kafka集群中,每个代理节点(Broker)在启动都会实例化一个KafkaController类。该类会执行一系列业务逻辑,选举出主题分区的leader节点。
(1)第一个启动的代理节点,会在Zookeeper系统里面创建一个临时节点/Controller,并写入该节点的注册信息,使该节点成为控制器。
(2)其他代理节点陆续启动时,也会尝试在zookeeper系统里面创建/controller节点。但是由于/controller节点已经存在,所以会抛出
创建/controller节点失败的异常信息。创建失败的代理节点会根据返回的结果,判断出在kafka集群中已经有一个控制器被创建成功了,
所以放弃创建/controller节点。这样确保了kafka集群控制器的唯一性。
(3)其他的代理节点,会在控制器上注册相应的监听器。各个监听器监听各自代理节点的状态变化,当监听到节点状态变化时,会触发相应的监听函数进行处理。
分区多副本选主
`【优点】实现简单
`【缺点】Herd Effect(群选举); Zookeeper负载过重; Latency(潜在因素)较大;

总结:缺点很明显,假设有很多个kafka的broker,每个broker又有多个topic,每个topic又有多个partition。这样各自为政的选举,相当耗性能的。


在kafka的集群中,会存在着多个主题topic,在每一个topic中,又被划分为多个partition,为了防止数据不丢失,每一个partition又有多个副本,在整个集群中,总共有三种副本角色:

首领副本(leader):也就是leader主副本,每个分区都有一个首领副本,为了保证数据一致性,所有的生产者与消费者的请求都会经过该副本来处理。
跟随者副本(follower):除了首领副本外的其他所有副本都是跟随者副本,跟随者副本不处理来自客户端的任何请求,只负责从首领副本同步数据,保证与首领保持一致。如果首领副本发生崩溃,就会从这其中选举出一个leader。
首选首领副本:创建分区时指定的首选首领。如果不指定,则为分区的第一个副本。
follower需要从leader中同步数据,但是由于网络或者其他原因,导致数据阻塞,出现不一致的情况,为了避免这种情况,follower会向leader发送请求信息,这些请求信息中包含了follower需要数据的偏移量offset,而且这些offset是有序的。

如果有follower向leader发送了请求1,接着发送请求2,请求3,那么再发送请求4,这时就意味着follower已经同步了前三条数据,否则不会发送请求4。leader通过跟踪 每一个follower的offset来判断它们的复制进度。

默认的,如果follower与leader之间超过10s内没有发送请求,或者说没有收到请求数据,此时该follower就会被认为“不同步副本”。而持续请求的副本就是“同步副本”,当leader发生故障时,只有“同步副本”才可以被选举为leader。其中的请求超时时间可以通过参数replica.lag.time.max.ms参数来配置。

我们希望每个分区的leader可以分布到不同的broker中,尽可能的达到负载均衡,所以会有一个首选首领,如果我们设置参数auto.leader.rebalance.enable为true,那么它会检查首选首领是否是真正的首领,如果不是,则会触发选举,让首选首领成为首领。
消费组选主 


在kafka的消费端,会有一个消费者协调器以及消费组,组协调器GroupCoordinator需要为消费组内的消费者选举出一个消费组的leader 

如果消费组内还没有leader,那么第一个加入消费组的消费者即为消费组的leader;
如果某一个时刻leader消费者由于某些原因退出了消费组,那么就会重新选举leader

private val members = new mutable.HashMap[String, MemberMetadata]
leaderId = members.keys.headOption
  上面代码是kafka源码中的部分代码,member是一个hashmap的数据结构,key为消费者的member_id,value是元数据信息,那么它会将leaderId选举为Hashmap中的第一个键值对。它和随机基本没啥区别

3.3 工作流程及文件存储机制

工作流程

  一个topic 是一个消息队列,生产者不停的往队列中生产数据,消费者不停的从队列中消费数据;
  kafka 中,以topic进行分类的,生产者生产消息,消费者消费消息,都是面向topic的;
  topic是逻辑上的概念,而paritition是物理上的概念,每个partition对应于一个log文件,该log文件中存储的就是producer生产的数据,producer生产的数据会不断追加到该log文件末端,且每条数据都有自己offset,消费者组中的每个消费者,都会实时的记录自己消费到了那条offset,以便于出错恢复时,从上次的位置继续消费。
partition:提高扩展性和吞吐量,kafka的数据是以paritition为存储单位;
一个partition就是一个log不停追加的数据文件;

kafka文件存储机制

   由于生产者生产的消息会不断追加log文件末尾,为防止log文件过大,导致数据定位效率低下,kafka 采用了分片和索引机制,将每个partition分为多个segment。
每个segment对应两个文件 
   ".index"文件
   ".log"  文件
这些文件位于一个文件夹下,该文件夹的命名规则为:topic 名称+分区序号, 例如。first 这个topic有三个分区,则其对应文件夹为first-0 first-1 first-2

3.4 kafka的zookeeper存储结构图

第四节

kafka集群搭建

4.1 下载

kafka下载地址

wget https://mirrors.aliyun.com/apache/kafka/2.5.1/kafka_2.12-2.5.1.tgz
4.2 部署

解压kafka

tar xvf kafka_2.12-2.5.1.tgz -C /data/
4.3 配置

参考链接

开源中国

集群配置

提示:如下集群配置是在同一台机器中(伪集群),配置文件名称可自定义,后续集群启动指定配置文件即可

kafka集群

kafka1

vim /data/kafka/conf/server1.conf
broker.id=0                          #不唯一
listeners=PLAINTEXT://192.168.24.128:9092
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
log.dirs=/tmp/kafka-logs
num.partitions=1
num.recovery.threads.per.data.dir=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
zookeeper.connect=192.168.24.128:2181,192.168.24.128:2182,192.168.24.128:2183
zookeeper.connection.timeout.ms=18000
group.initial.rebalance.delay.ms=0

kafka2

vim /data/kafka/conf/server2.conf
broker.id=3
listeners=PLAINTEXT://192.168.24.128:9093
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
log.dirs=/tmp/kafka2-logs
num.partitions=1
num.recovery.threads.per.data.dir=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
zookeeper.connect=192.168.24.128:2181,192.168.24.128:2182,192.168.24.128:2183
zookeeper.connection.timeout.ms=18000
group.initial.rebalance.delay.ms=0                                

kafka3

vim /data/kafka/conf/server3.conf
broker.id=4
listeners=PLAINTEXT://192.168.24.128:9094
num.network.threads=3
num.io.threads=8
socket.send.buffer.bytes=102400
socket.receive.buffer.bytes=102400
socket.request.max.bytes=104857600
log.dirs=/tmp/kafka3-logs
num.partitions=1
num.recovery.threads.per.data.dir=1
offsets.topic.replication.factor=1
transaction.state.log.replication.factor=1
transaction.state.log.min.isr=1
log.retention.hours=168
log.segment.bytes=1073741824
log.retention.check.interval.ms=300000
zookeeper.connect=192.168.24.128:2181,192.168.24.128:2182,192.168.24.128:2183
zookeeper.connection.timeout.ms=18000
group.initial.rebalance.delay.ms=0
4.4 启动

kafka集群启动 指定配置文件

./kafka-server-start.sh  -daemon ../config/server1.properties 
./kafka-server-start.sh  -daemon ../config/server2.properties 
./kafka-server-start.sh  -daemon ../config/server3.properties  
4.5 topic基本使用
`topic   主题即队列

 kafka-topics.sh 用于topic的查询,创建,删除等操作

【4.5.1】 topic创建

--topic 定义topic 名称为second
--replication-factor 定义副本数
--partitions 定义分区数

./kafka-topics.sh --zookeeper 127.0.0.1:2181  --create --replication-factor 3 -partitions 1 --topic second

【4.5.2】 查看 topic 的信息

--describe 具体的topic信息描述

./kafka-topics.sh  --zookeeper 127.0.0.1:2182 --topic second --describe

【4.5.3】 topic 查询

./kafka-topics.sh  --zookeeper 127.0.0.1:2182 --list

【4.5.4】 topic 删除

删除 名为second的topic 【并不是真正的删除,需要在server.prople中配置】

./kafka-topics.sh  --zookeeper 127.0.0.1:2181  --topic second --delete

kafka删除topic

【4.5.5】 压测

生产测试

消费测试

详细见参考链接

压测

kafka压测

生产测试:

[cat@kafka3 bin]$ ./kafka-producer-perf-test.sh --topic three  --num-records 100000 --record-size 1000  --throughput 2000   --producer-props  bootstrap.servers=192.168.24.137:9092

说明:
 --topic topic名称,本例为three
--num-records 总共需要发送的消息数,本例为100000
--record-size 每个记录的字节数,本例为1000
--throughput 每秒钟发送的记录数,本例为5000
--producer-props bootstrap.servers=localhost:9092 (发送端的配置信息,本次测试取集群服务器中的一台作为发送端,可在kafka的config目录,以该项目为例:/usr/local/kafka/config;查看server.properties中配置的zookeeper.connect的值,默认端口:9092) 


消费测试:

[cat@kafka3 bin]$ ./kafka-consumer-perf-test.sh --broker-list=192.168.24.137:9092   --topic three -fetch-size 104856 -messages 100000 --threads 1 

说明:
kafka-consumer-perf-test.sh 脚本命令的参数为:
--zookeeper 指定zookeeper的链接信息,本例为localhost:2181 ;
--topic 指定topic的名称,本例为test_perf,即4.2.1中写入的消息;
--fetch-size 指定每次fetch的数据的大小,本例为1048576,也就是1M
--messages 总共要消费的消息个数,本例为1000000,100w
posted @ 2021-11-25 15:51  名字长的像一只老山羊  阅读(57)  评论(0编辑  收藏  举报