kafka 随笔
一 kafka概述
1.1 kafka是什么
在流式计算中,kafka一般涌来缓存数据,storm通过消费kafka的数据进行计算。kafka是一个分布式的消息队列。kafka对消息保存时根据topic进行归类,发送消息者成为producer(生产者),消息接受者称为consumer(消费者)此外kafka集群有多个kafka实例组成,每个实例(server)称为broker。其中kafka集群依赖于zookeeper集群来保存一些meta信息,保证系统的可用性。
1.2 kafka内部实现原理
(1)点对点模式,即一对一,消费者主动拉取数据,消息收到后消息清除。点对点模式通常是一个基于拉取或者轮询的消息传送模型,这种模型从队列中请求信息,而不是将消息推送到客户端,这个模型的特点是发送到队列的消息被一个且只有一个接收者接收处理,即使有多个消息坚挺着也是如此。
(2)发布/订阅模式,即一对多,数据尝试后,推送给所有订阅者。发布订阅模式是基于推送消息传送模型,发布订阅模型可以有多重不同的订阅者,临时订阅者只在主动监听朱婷时才接收信息,而持久订阅者则监听主题的所有信息,即使当前订阅者不可用。
1.3 消息队列的优势
(1)解耦
(2)冗余
(3)可扩展
(4)灵活性
(5)可恢复性
(6)顺序保证
(7)缓冲
(8)异步通信
1.4 kafka架构
1)Producer: 消息生产者,向kafka broker发送消息的客户端。2)Consumer: 消息消费者,向kafka broker 取消息的客户端。
3)Topic : 队列
4)Consumer Group(CG):kafka用来实现一个topic消息的广播,发送给所有的consumer和发送任意一个consumer的手段,一个topic可以多个CG,topic的消息回复制到多个CG,但每个partition只会把消息发给该CG中的一个consumer,如果需要实现广播,只要每个consumer有一个独立的CG就可以了,要实现单播只要所有的consumer在同一个CG,用CG还可以将consumer进行自由的分组而不需要多次发送消息到不同的topic。
5)Broker:一台kafka服务器就是一个broker,一个集群由多个broker组成,一个broker可以容纳多个topic。
6)Protition:为了实现扩展性,一个非常大的topic可以分布到多个broker上,一个topic可以分为多个partition,每个partition是一个有序的队列,partition中的每条消息都会被分配一个有序的id(offset)。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的整体(多个partition之间)的顺序。
7)Offset:kafka的存储文件都是按照offset.kafka来命名,用offset做名字的好处是方便查找,如果想查找位于2049的位置,只要找到2048.kafka的文件即可。
二 kafka集群搭建
2.1 集群环境
1)jdk 环境
2)zookeeper 环境
2.2集群部署
1)解压kafka安装包
1 [zhihua@nna /soft]$tar -xzvf kafka_2.11-2.0.0.tgz
2)创建软连接
1 [zhihua@nna /soft]$ln -s kafka_2.11-2.0.0 kafka
3)在/soft/kafka 目录下创建logs文件夹
1 [zhihua@nna /soft/kafka]$mkdir logs
4)修改配置文件
1 [zhihua@nna /soft/kafka]$cd config/ 2 [zhihua@nna /soft/kafka/config]$vim server.properties
1 #broker的全局唯一编号,不能重复 2 broker.id=0 3 4 #删除topic功能使能 5 6 delete.topic.enable=true 7 8 #处理网络请求的线程数量 9 10 num.network.threads=3 11 12 #用来处理磁盘IO的现成数量 13 14 num.io.threads=8 15 16 #发送套接字的缓冲区大小 17 18 socket.send.buffer.bytes=102400 19 20 #接收套接字的缓冲区大小 21 22 socket.receive.buffer.bytes=102400 23 24 #请求套接字的缓冲区大小 25 26 socket.request.max.bytes=104857600 27 28 #kafka运行日志存放的路径 29 30 log.dirs=/soft/kafka/logs 31 32 #topic在当前broker上的分区个数 33 34 num.partitions=1 35 36 #用来恢复和清理data下数据的线程数量 37 38 num.recovery.threads.per.data.dir=1 39 40 #segment文件保留的最长时间,超时将被删除 41 42 log.retention.hours=168 43 44 #配置连接Zookeeper集群地址 45 46 zookeeper.connect=dn1:2181,dn2:2181,dn3:2181
5)配置环境变量
```
1 [root@nna /root]#vim /etc/profile
1 # kafka 2 export KAFKA_HOME=/soft/kafka 3 export PATH=$PATH:$KAFKA_HOME/bin
1 [root@nna /root]#source /etc/profile
6)分发至安装包至集群机器
1 [zhihua@nna /soft]$scp -r kafka_2.11-2.0.0 zhihua@dn1:/soft/ 2 [zhihua@nna /soft]$scp -r kafka_2.11-2.0.0 zhihua@dn2:/soft/ 3 [zhihua@nna /soft]$scp -r kafka_2.11-2.0.0 zhihua@dn3:/soft/
7)更改集群其他机器配置文件
在dn1、dn2、dn3修改配置文件将/soft/kafka/config/server.properties中的broker.id值修改为1、2、3。其broker.id值不得重复。
8)启动kafka集群
1 [zhihua@nna /soft/kafka]$bin/kafka-server-start.sh config/server.properties & 2 [zhihua@dn1 /soft/kafka]$bin/kafka-server-start.sh config/server.properties & 3 [zhihua@dn2 /soft/kafka]$bin/kafka-server-start.sh config/server.properties & 4 [zhihua@dn3 /soft/kafka]$bin/kafka-server-start.sh config/server.properties &
2.3 kafka命令行操作
1)查看当前服务器中的所有topic
1 [zhihua@nna /soft/kafka]$bin/kafka-topics.sh --list --zookeeper dn1:2181
2)创建一个topic
1 [zhihua@nna /soft/kafka]$bin/kafka-topics.sh --create --zookeeper dn1:2181 --replication-factor 4 --partitions 1 --topic first
**参数解释:**
--topic 定义topic名称
--replication-factor 定义副本数
--partitions 定义分区数
3)删除topic
1 [zhihua@nna /soft/kafka]$bin/kafka-topics.sh --delete --zookeeper dn1:2181 --topic first
此操作需要在server.properties中设置delete.topic.enable=true 否则只是标记删除,或者直接启动。
4)生产消息
1 [zhihua@nna /soft/kafka]$bin/kafka-console-producer.sh --broker-list dn1:9092 --topic first 2 >hello
5)消费消息
1 [zhihua@dn1 /soft/kafka]$bin/kafka-console-consumer.sh --zookeeper dn1:2181 --from-beginning --topic first
6)查看某个topic详情
1 [zhihua@dn1 /soft/kafka]$bin/kafka-topics.sh --topic first --describe --zookeeper dn1:2181
三 kafka工作流程分析
3.1 kafka生产过程分析
3.1.1 写入方式
producer采用推(push)模式将消息发布到broker,每条消息都被追加(append)到分区(partition)中,属于顺序写磁盘(顺序写磁盘效率要比随机写内存高,保障kafka吞吐量)。
3.1.2 分区(partition)
消息发送时都被发送到一个topic,其本质就是一个目录,而topic是由一些partition logs(分区日志)组成,其组织结构如下图所示:
由此图可以看到每个partition中的消息都是有序的,生产的消息被不断追加到partition log上,其中的每一个消息都被赋予了一个唯一的offset值。
1)分区的原因:
<1> 方便在集群中扩展,每个partition可以通过调整以适应它所在的机器,而一个topic又可以有多个partition组成,因此整个集群就可以适应任意大小的数据。
<2> 可以提高并发,因为可以以partition为单位进行读写。
2)分区的原则
<1> 指定了partition,则可以直接使用。
<2> 未指定partition但指定key,通过对key的value 进行hash出一个partition。
<3> partition和key都未指定,使用轮询方式选出一个partition。
3.1.3 副本(Replication)
同一个partition可能会有多个replication(对应 server,properties配置中的default.replication.factor=N)。没有replication的情况下,一旦broker宕机,其所有partition数据都不可被消费,同时producer也不能再将数据存于其partition。引入replication之后,同一个partition可能会有多个replication。而这时需要在这些replication之间选出一个leader。producer和consumer只与这个leader交互,其replication作为follower从leader中复制数据。
3.1.4 写入流程
1)producer先从zookeeper的‘/brokers/.../state’节点找到该partition的leader。
2)producer将消息发送给该leader。
3)leader将消息写入本地log。
4)follower 从leader pull消息,写入本地log后向leader发送ACK。
5)leader收到所有ISR中的replication的ACK后,增加HW(high watermark 最后commit的offset)并向producer发送ACK。
3.2 kafka 消费保存
3.2.1 kafka存储方式
在物理上把topic分成一个或者多个partition对应server.properties中的num.partitions=3配置,每个partition物理上对应一个文件夹,
1 drwxrwxr-x 2 zhihua zhihua 4096 Apr 24 09:49 mytopic-0 2 drwxrwxr-x 2 zhihua zhihua 4096 Apr 24 14:35 mytopic-1 3 drwxrwxr-x 2 zhihua zhihua 4096 Apr 24 14:35 mytopic-2
3.2.2 kafka存储策略
无论消息是否被消费,kafka都会将消息进行保留,有两种策略可以删除旧数据如下:
1)基于时间,log.retention.hours=168
2)基于大小,log.retention.bytes=1073741824
kafka读读特定消息的时间复杂度为O(1),与文件大小无关,所以删除过期的文件与提高kafka的性能无关。
3.3 kafka消费者组
3.3.1 什么是kafka消费者组
kafka consumer group是kafka提供的可扩展且具有容错性的消费者机制,消费者组中有多个消费者或消费者实例,它们共享一个公共的ID,即group ID。组内的所有消费者协调在一起来消费订阅主题的所有分区,每个分区只能由一个消费者组内的一个consumer来进行消费。其consumer group具有以下特性:
1)consumer group 下可以有一个或多个 consumer instance consumer instance可以是一个进程,也可以是一个线程。
2)group.id 是一个字符串,唯一标识一个consumer group
3)consumer group 下订阅的topic下的每个分区只能分配给某个 group下 的一个consumer(还可以分配给其他的group)
3.3.1 消费者位置(consumer position)
消费者在消费的过程中需要记录自己消费了多少数据,这个叫消费位置信息,在kafka中用offset来形容。很多消息引擎都会把这部分消息保存在broker端。但是会出现以下问题:
1)broker从西变成有状态的,会影响伸缩性。
2)需要引入应答机制来确认消费是否成功.
3)由于要保存很多consumer的offset信息,必然引入复杂的数据结构,构成资源浪费,而kafka选择了不同的方式,每个consumer group 保存自己的唯一信息,那么直需要简单的一个整数表示位置就够了, 同时可以引入checkpoint 机制定期持久化,简化了应答机制的实现。