概述
Kafka是Apache下的一个子项目,是一个高性能跨语言分布式发布/订阅消息队列系统,而Jafka是在Kafka之上孵化而来的,即Kafka的一个升级版。具有以下特性:快速持久化,可以在O(1)的系统开销下进行消息持久化;高吞吐,在一台普通的服务器上既可以达到10W/s的吞吐速率;完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动实现负载均衡;支持Hadoop数据并行加载,对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案。Kafka通过Hadoop的并行加载机制统一了在线和离线的消息处理。Apache Kafka相对于ActiveMQ是一个非常轻量级的消息系统,除了性能非常好之外,还是一个工作良好的分布式系统。
相关概念
Broker
Kafka集群包含一个或多个服务器,这种服务器被称为broker
Topic
Kafka中的Message是以topic为基本单位组织的,不同的topic之间是相互独立的。每个topic又可以分成几个不同的partition(每个topic有几个partition是在创建topic时指定的),每个partition存储一部分Message。
(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上,但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)
Partition
Partition是物理上的概念,每个Topic包含一个或多个Partition. partition是以文件的形式存储在文件系统中
Producer
负责发布消息到Kafka broker
Consumer
消息消费者,向Kafka broker读取消息的客户端。
Consumer Group
每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)。
在消费者消费消息时,kafka使用offset来记录当前消费的位置。
在kafka的设计中,可以有多个不同的group来同时消费同一个topic下的消息,如图,有两个不同的group同时消费,它们的的消费的记录位置offset各不项目,不互相干扰。
对于一个group而言,消费者的数量不应该多余分区的数量,因为在一个group中,每个分区至多只能绑定到一个消费者上,即一个消费者可以消费多个分区,一个分区只能给一个消费者消费。因此,若一个group中的消费者数量大于分区数量的话,多余的消费者将不会收到任何消息
Kafka的架构简化如下图所示。因为Kafka内在就是分布式的,一个Kafka集群通常包括多个代理。为了均衡负载,将Topic分成多个分区,每个代理存储一或多个分区。多个生产者和消费者能够同时生产和获取消息。
zookeeper 节点
kafka 在 zookeeper 中的存储结构如下图所示
部署kafka
过程如下(以下以meteor server 为例,其它server配置大致相同):
下载
[root@meteor ~]# wget http://mirror.bit.edu.cn/apache/kafka/1.0.0/kafka_2.12-1.0.0.tgz
--2018-06-11 19:40:49-- http://mirror.bit.edu.cn/apache/kafka/1.0.0/kafka_2.12-1.0.0.tgz
正在解析主机 mirror.bit.edu.cn (mirror.bit.edu.cn)... 114.247.56.117
正在连接 mirror.bit.edu.cn (mirror.bit.edu.cn)|114.247.56.117|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:44352403 (42M) [application/octet-stream]
正在保存至: “kafka_2.12-1.0.0.tgz”
100%[===========================>] 44,352,403 497KB/s 用时 1m 44s
2018-06-11 19:42:33 (417 KB/s) - 已保存 “kafka_2.12-1.0.0.tgz” [44352403/44352403])
解压
[root@meteor ~]# tar xfz kafka_2.12-1.0.0.tgz -C /usr/local/
[root@meteor ~]# cd /usr/local/
[root@meteor local]# ln -s kafka_2.12-1.0.0 kafka
[root@meteor local]# cd kafka
[root@meteor kafka]# ls
bin config libs LICENSE NOTICE site-docs
配置zookeeper
[root@meteor kafka]# vim config/zookeeper.properties
[root@meteor kafka]# grep -Pv "^(#|$)" config/zookeeper.properties
dataDir=/usr/local/kafka/zkdata
dataLogDir=/usr/local/kafka/zklogs
clientPort=2181
maxClientCnxns=0
server.3=meteor\:2888\:3888
server.2=vm2\:2888\:3888
server.1=vm1\:2888\:3888
initLimit=10
syncLimit=5
tickTime=2000
[root@meteor kafka]# mkdir zkdata
[root@meteor kafka]# mkdir zklogs
[root@meteor kafka]# echo 3 > zkdata/myid
[root@meteor kafka]#
配置kafka
[root@meteor kafka]# vim config/server.properties
[root@meteor kafka]# grep -Pv "^(#|$)" config/server.properties
broker.id=3
listeners=PLAINTEXT://:9092
advertised.listeners=PLAINTEXT://meteor: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=/usr/local/kafka/kfklogs
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=vm1:2181,vm2:2181,meteor:2181
zookeeper.connection.timeout.ms=6000
group.initial.rebalance.delay.ms=0
[root@meteor kafka]# mkdir kfklogs
[root@meteor kafka]#
配置producer、consumer
[root@meteor kafka]# vim config/producer.properties
[root@meteor kafka]# grep -Pv "^($|#)" config/producer.properties
bootstrap.servers=vm1:9092,vm2:9092,meteor:9092
compression.type=none
[root@meteor kafka]#
[root@meteor kafka]# vim config/consumer.properties
[root@meteor kafka]# grep -Pv "^($|#)" config/consumer.properties
bootstrap.servers=vm1:9092,vm2:9092,meteor:9092
group.id=test-consumer-group
[root@meteor kafka]#
启动所有server的zookeeper
[root@meteor kafka]# bin/zookeeper-server-start.sh -daemon config/zookeeper.properties
[root@meteor kafka]# echo stat | nc localhost 2181
Zookeeper version: 3.4.10-39d3a4f269333c922ed3db283be479f9deacaa0f, built on 03/23/2017 10:13 GMT
Clients:
/0:0:0:0:0:0:0:1:60620[0](queued=0,recved=1,sent=0)
Latency min/avg/max: 0/0/0
Received: 1
Sent: 0
Connections: 3
Outstanding: 0
Zxid: 0x100000000
Mode: leader
Node count: 4
[root@meteor kafka]#
测试zookeeper
[root@meteor kafka]# bin/zookeeper-shell.sh localhost:2181
Connecting to localhost:2181
Welcome to ZooKeeper!
JLine support is disabled
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
ls /
[zookeeper]
quit
Quitting...
[root@meteor kafka]#
启动所有server的kafka ,再观察zookeeper的注册情况
[root@meteor kafka]# bin/kafka-server-start.sh -daemon config/server.properties
[root@meteor kafka]# bin/zookeeper-shell.sh localhost:2181
Connecting to localhost:2181
Welcome to ZooKeeper!
JLine support is disabled
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
ls /
[cluster, controller, controller_epoch, brokers, zookeeper, admin, isr_change_notification, consumers, log_dir_event_notification, latest_producer_id_block, config]
ls /brokers/ids
[1, 2, 3]
get /brokers/ids/1
{"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://vm1:9092"],"jmx_port":-1,"host":"vm1","timestamp":"1528692750016","port":9092,"version":4}
cZxid = 0x10000002a
ctime = Mon Jun 11 20:51:45 CST 2018
mZxid = 0x10000002a
mtime = Mon Jun 11 20:51:45 CST 2018
pZxid = 0x10000002a
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x163ed2c96b00001
dataLength = 176
numChildren = 0
get /brokers/ids/2
{"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://vm2:9092"],"jmx_port":-1,"host":"vm2","timestamp":"1528692769621","port":9092,"version":4}
cZxid = 0x10000002f
ctime = Mon Jun 11 20:52:04 CST 2018
mZxid = 0x10000002f
mtime = Mon Jun 11 20:52:04 CST 2018
pZxid = 0x10000002f
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x263ed2ce0870002
dataLength = 176
numChildren = 0
get /brokers/ids/3
{"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://meteor:9092"],"jmx_port":-1,"host":"meteor","timestamp":"1528721489008","port":9092,"version":4}
cZxid = 0x100000025
ctime = Mon Jun 11 20:51:29 CST 2018
mZxid = 0x100000025
mtime = Mon Jun 11 20:51:29 CST 2018
pZxid = 0x100000025
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x263ed2ce0870001
dataLength = 182
numChildren = 0
quit
Quitting...
[root@meteor kafka]#
创建topic
[root@meteor kafka]# bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 2 --partitions 2 --topic topic01
Created topic "topic01".
[root@meteor kafka]# bin/kafka-topics.sh --list --zookeeper localhost:2181
topic01
[root@meteor kafka]# bin/kafka-topics.sh --describe --zookeeper localhost:2181
Topic:topic01 PartitionCount:2 ReplicationFactor:2 Configs:
Topic: topic01 Partition: 0 Leader: 2 Replicas: 2,3 Isr: 2,3
Topic: topic01 Partition: 1 Leader: 3 Replicas: 3,1 Isr: 3
[root@meteor kafka]#
[root@meteor kafka]# bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic topic02
Created topic "topic02".
创建一个消息生产者
[root@meteor kafka]# bin/kafka-console-producer.sh --broker-list localhost:9092 --topic topic02
>hello kafka
>hello world
创建一个消息消费者
[root@vm1 kafka]# bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic topic02 --from-beginning
hello kafka
hello world
创建一个消息消费者
[root@vm2 kafka]# bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic topic02 --from-beginning
hello kafka
hello world