Kafka技术栈实用版
Kafka简介
Kafka是最初由Linkedin公司开发,是⼀个分布式、支持分区的(partition)、多副本的 (replica),基于zookeeper 协调的分布式消息系统,它的最⼤的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、 Storm/Spark流式处理引擎,web/nginx日志、访问日志,消息服务等等,用scala语言编写,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。
一、Kafka基础
1、kafka的安装部署
1)JDK环境和Zookeeper环境的搭建。
JDK downloads:https://www.oracle.com/java/technologies/downloads/
Zookeeper downloads:http://zookeeper.apache.org/releases.html
2)下载Kafka的安装包:http://kafka.apache.org/downloads
3)上传到kafka目录上: /usr/local/kafka,解压。
4)进⼊到config⽬录内,修改server.properties
#broker.id属性在kafka集群中必须要是唯⼀
broker.id=0
#kafka部署的机器ip和提供服务的端⼝号
listeners=PLAINTEXT://x.x.x.x:9092
#kafka的消息存储⽂件
log.dir=/usr/local/data/kafka-logs
#kafka连接zookeeper的地址
zookeeper.connect=x.x.x.x:2181
5)进⼊到bin⽬录内,执⾏以下命令来启动kafka服务器(带着配置⽂件
./kafka-server-start.sh -daemon ../config/server.properties
6)检测Kafka是否启动成功:
进⼊到zk内查看是否有kafka的节点: /brokers/ids/0
2、Kafka的基本概念
名称 | 解释 |
---|---|
Broker | 消息中间件处理节点(kafka服务器),⼀个Kafka节点就是⼀个broker,⼀个或者多个Broker可以组成⼀个Kafka集群。 |
Topic | Topic 是逻辑上的概念,Kafka根据topic对消息进⾏归类,发布到Kafka集群的每条消息都需要指定⼀个topic。 |
Producer | 消息⽣产者,向Broker发送消息的客户端。 |
Consumer | 消息消费者,从Broker读取消息的客户端。 |
3、创建topic
通过kafka命令向zk中创建⼀个主题:
./kafka-topics.sh --create --zookeeper x.x.x.x:2181 --replication-factor 1 --partitions 1 --topic test
查看当前zk中所有的主题:
./kafka-topics.sh --list --zookeeper x.x.x.x:2181 test
删除Topic:
bin/kafka-topics.sh --zookeeper x.x.x.x:2181 --delete --topic test
注:需要server.properties中设置delete.topic.enable=true否则只是标记删除(如果当前Topic没有使用过,即没有传输过信息,则可以彻底删除。)。
4、发送与消费消息
发送消息:
把消息发送给broker中的某个topic,打开⼀个kafka发送消息的客户端,然后开始⽤客户端向
kafka服务器发送消息。
./kafka-console-producer.sh --bootstrap-server x.x.x.x:9092 --topic test
或
./kafka-console-producer.sh --broker-list x.x.x.x:9092 --topic test
–bootstrap-server:指定了连接kafka集群的地址。
–broker-list:指定了连接kafka集群的地址。
消费消息:
打开⼀个消费消息的客户端,向kafka服务器的某个主题消费消息。
⽅式⼀:从当前主题中的最后⼀条消息的offset(偏移量位置)+1开始消费。
./kafka-console-consumer.sh --bootstrap-server x.x.x.x:9092 --topic test
⽅式⼆:从当前主题中的第⼀条消息开始消费。
./kafka-console-consumer.sh --bootstrap-server x.x.x.x:9092 --from-beginning --topic test
5、消息的细节
1)生产者将消息发送给broker,broker会将消息保存在本地的日志文件中。
/usr/local/kafka/data/kafka-logs/主题-分区/00000000.log
2)消息的保存是有序的,通过offset偏移量来描述消息的有序性。
3)消费者消费消息时也是通过offset来描述当前要消费的那条消息的位置。
6、查看消费组的详细信息
通过以下命令可以查看到消费组的相关信息:
./kafka-consumer-groups.sh --bootstrap-server x.x.x.x:9092 --describe --group testGroup
重点关注以下信息:
current-offset:最后被消费的消息的偏移量。
Log-end-offset:消息总量(最后⼀条消息的偏移量)。
Lag:积压了多少条消息。
二、Kafka主题与分区
1、Topic
主题(topic)在kafka中是⼀个逻辑的概念,kafka通过topic将消息进行分类。不同的topic会被
订阅该topic的消费者消费。
但是有⼀个问题,如果说这个topic中的消息非常非常多,多到需要几T来存,因为消息是会被
保存到log日志文件中的。为了解决这个文件过大的问题,kafka提出了Partition分区的概念。
2、Partition
1)分区的概念
通过partition将⼀个topic中的消息分区来存储。这样的好处有多个:
a)分区存储,可以解决统⼀存储文件过大的问题(分布式存储)。
b)提供了读写的吞吐量:读和写可以同时在多个分区中进行(可以并行写)。
1.1)分区的策略
- 轮询分配策略(默认)
如果在生产消息时,key为null,则使用轮询算法均衡地分配分区。 - 随机策略(早版本默认,现已不是)
也是为了均匀的写入到每个分区,但后续轮询策略表现更佳,故很少使用随机策略了。 - 按Key分配策略
按key分配策略,有可能出现“数据倾斜”。例如,某个key包含了大量的数据,因为key值一样,所以所有的数据将都分配到一个分区中,造成该分区的数量远大于其他的分区。
2)创建多分区的主题
./kafka-topics.sh --create --zookeeper x.x.x.x:2181 --replication-factor 1 --partitions 2 --topic test1
查看topic的分区信息
./kafka-topics.sh --describe --zookeeper x.x.x.x:2181 --topic test1
修改分区数量
bin/kafka-topics.sh --zookeeper hadoop102:2181 --alter --topic first --partitions 6
注:修改分区数时,仅能增加分区个数。若是使其减少partition个数,则会报错。
3、Kafka日志文件
1)000000000.log: 这个文件中保存的就是消息。
2)__consumer_offsets-49:
kafka内部自己创建了__consumer_offsets主题包含了50个分区(通过offsets.topic.num.partitions设置)。这个主题用来存放消费者消费某个主题的偏移量(offset)。因为每个消费者都会自己维护着消费的主题的偏移量,也就是说每个消费者会把消费的主题的偏移量自主上报给kafka中的默认主题 consumer_offsets。因此kafka为了提升这个主题的并发性,默认设置了50个分区。
- 提交到哪个分区:通过hash函数:hash(consumerGroupId) % __consumer_offsets主题的分区数
- 提交到该主题中的内容是:key是consumerGroupId+topic+分区号,value就是当前offset的值。
3)文件中保存的消息,默认保存7天。七天到后消息会被删除。
三、Kafka集群
1、搭建Kafka集群(3个broker)
准备3个server.properties文件,每个文件中的这些内容要调整:
server.properties
broker.id=0
listeners=PLAINTEXT://x.x.x.x:9092
log.dir=/usr/local/data/kafka-logs
server1.properties
broker.id=1
listeners=PLAINTEXT://x.x.x.x:9093
log.dir=/usr/local/data/kafka-logs-1
server2.properties
broker.id=2
listeners=PLAINTEXT://x.x.x.x:9094
log.dir=/usr/local/data/kafka-logs-2
然后分别启动三个brokers:
./kafka-server-start.sh -daemon ../config/server.properties
搭建完后通过查看zk中的/brokers/ids 看是否启动成功。
2、副本(Replication)
副本是对分区的备份。在集群中,不同的副本会被部署在不同的broker上。下面例子:创建1
个主题,2个分区、3个副本。
./kafka-topics.sh --create --zookeeper x.x.x.x:2181 --replication-factor 3 --partitions 2 --topic my-replicated-topic
通过查看主题信息,其中的关键数据:
- replicas:
当前副本存在的broker节点 。 - leader:副本里的概念
每个partition都有⼀个broker作为leader。
消息发送方要把消息发给哪个broker?就看副本的leader是在哪个broker上面。副本里的leader专门用来接收消息。接收到消息,其他follower通过poll的方式来同步数据。 - follower:leader处理所有针对这个partition的读写请求,而follower被动复制leader,不提供读写(主要是为了保证多副本数据与消费的⼀致性),如果leader所在的broker挂掉,那么就会进行新leader的选举,至于怎么选,在之后的controller的概念中介绍。
- ISR:
可以同步的broker节点和已同步的broker节点,存放在ISR集合中。
kafka集群中由多个broker组成。
⼀个broker中存放⼀个topic的不同partition——副本。
3、集群消息发送与消费
Kafka集群消息的发送:
./kafka-console-producer.sh --broker-list x.x.x.x:9092, x.x.x.x:9093, x.x.x.x:9094 --topic my-replicated-topic
Kafka集群消息的消费:
./kafka-console-consumer.sh --bootstrap-server x.x.x.x:9092, x.x.x.x:9093, x.x.x.x:9094 --from-beginning --topic my-relicated-topic
指定消费组来消费消息:
./kafka-console-consumer.sh --bootstrap-server x.x.x.x:9092, x.x.x.x:9093, x.x.x.x:9094 --from-beginning --consumer-property group.id=testGroup1 --topic my-replicated-topic
4、分区消费组的消费者细节
- 图中Kafka集群有两个broker,每个broker中有多个partition。⼀个partition只能被⼀个消费组里的某⼀个消费者消费,从而保证消费顺序。K