开启kafka服务:
开启系统自带zookeeper:./bin/zookeeper-server-start.sh config/zookeeper.properties &
开启自己配置的zookeeper:./bin/zkCli.sh start
开启kafka集群:./bin/kafka-server-start.sh config/server.properties &
创建topic:(创建一个叫做test的topic,只有一个分区,一个副本) ./bin/kafka-topics.sh --create --zookeeper node:2181 --replication-factor 1 --partitions 1 --topic test
查看创建的topic:./bin/kafka-topics.sh --list --zookeeper node:2181
生产者发送消息:./bin/kafka-console-producer.sh --broker-list node:9092 --topic test
aaaaa
消费者获取消息并输出:./bin/kafka-console-consumer.sh --zookeeper node:2181 --topic test --from-beginning
搭建1个多个broker的集群:
cp config/server.properties config/server-1.properties
cp config/server.properties config/server-2.properties
原来的server.properties文件:
broker.id=0
port=9092
log.dir=/.../kafka-logs
修改properties:
server-1.properties:
broker.id=1
port=9093
log.dir=/.../kafka-logs-1
server-2.properties:
broker.id=2
prot=9094
log.dir=/.../kafka-logs-2
创建一个拥有三个副本的topic:
./bin/kafka-topics.sh --create --zookeeper node:2181 --replication-factor 3 --partitions 1 --topic my-replicated-topic
查看节点信息:
./bin/kafka-topics.sh --describe --zookeeper node:2181 --topic my-replicated-topic
Topic:my-replicated-topic PartitionCount:1 ReplicationFactor:3 Configs:
Topic: my-replicated-topic Partition: 0 Leader: 1 Replicas: 1,2,0 Isr: 1,2,0
第一行是对所有分区的一个描述,然后每个分区都会对应一行,因为我们只有一个分区所以下面就只加了一行。
leader:负责处理消息的读和写,leader是从所有节点中随机选择的.
replicas:列出了所有的副本节点,不管节点是否在服务中.
isr:是正在服务中的节点.
使用客户端远程连接kafka的时候记得要保证客户端和服务端的kafka版本一致。不然连接不会成功。(之前在IDEA中尝试使用客户端连接kafka失败,原因是IDEA使用的kafka版本和虚拟机上的kafka版本不一致,导致连接失败)
Consumer Group:
定义了一组消费者。一般来说消息中间件都有两种模式:队列模式和发布订阅模式。队列模式及每一个消息都会给其中一个消费者,而发布订阅模式则是每个消息都广播给所有的消费者。Kafka就是使用了Consumer Group来实现了这两种模式。
如果所有的消费者都是同一个Consumer Group的话,就是队列模式,每个消息都会负载均衡的分配到所有的消费者。
理解:
在kafka中,对于每个topic,可以创建一个或者多个分区和副本。如果在一台机器上想要创建多个broker,那么每个broker的id必须不同,端口号也必须不同,kafka通过broker的id确定唯一的broker。如果不在一台机器上,那么broker还是不能一样,但是端口号可以使用默认的9092.
分区数可以大于broker的数量,但是副本数不能够大于broker的数量.如果每个topic配置的副本数为n,那么集群中允许有n-1个broker不工作,集群还是可以正常运行。
消费者组:
如果消费者配置的group.id一样的话,那么这些消费者属于同一个消费者组。如果消费者在用一个消费者组的话,那是采用的队列模式,每个消息都会负载均衡的分配到所有的消费者,也就是说,对于每个消费者,接收不到完整的生产者发送的消息,只能够接收部分生产者发送的消息,这个消费者组的所有消费者总的接收的消息才是集群中生产者发送的消息。
对于不同的消费者组,之间没有关系,采用的是发布订阅模式,每个消费者组都可以接收到生产者发送的消息,彼此之间互不干扰。
如果一个消费者组只有一个消费者的话,那么这个消费者可以接收到全部的生产者发布的消息。消费者订阅的是某个topic或者几个topic,和topic的分区,副本并没有直接的关系。
生产者:
生产者往topic上发布消息,可以指定发送到哪个分区,需要自定义分区函数。
对于有多个分区的topic,当接收到一条消息的时候,使用默认的分区函数,将消息发送给某个分区(可以自定义分区函数),也就是说,不同的分区,他们之间的数据是不相同的,分区之间也没有顺序可言。但是对于每个独立的分区,分区内的数据是有序的,先到的消息排在前,后到的消息排在后,并且每个分区都维护自己的一个offset。消费者订阅的是topic,也可以指定订阅哪个分区。
kafka的每个分区只能同时被一个消费者消费(一个消费者组内只有一个消费者可以消费这个分区),但是不同的消费者组可以同时消费这个分区。
消费者维护自己的offset。
kafka中删除某个topic的方法:
配置server.properties中delete.topic.enable=true;
删除topic的命令:./bin/kafka-topics.sh --delete --zookeeper node:2181 --topic test
如果topic只是被标记为marked for deletion,还是删除不掉,那么需要删除zookeeper目录下的topic
./bin/zkCli.sh rmr /brokers/topics/test
如果只是标记删除,记得删除zookeeper目录下的文件。
开启kafka服务进程:./bin/kafka-server-start.sh -daemon config/server.properties (添加daemon关键字)
Kafka运行时很少有大量读磁盘的操作,主要是定期批量写磁盘操作,因此操作磁盘很高效。这跟Kafka文件存储中读写message的设计是息息相关的。Kafka中读写message有如下特点:
写message:
消息从java堆转入page cache(即物理内存)。
由异步线程刷盘,消息从page cache刷入磁盘。
读message:
消息直接从page cache转入socket发送出去。
当从page cache没有找到相应数据时,此时会产生磁盘IO,从磁盘Load消息到page cache,然后直接从socket发出去
Kafka高效文件存储设计特点:
Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
通过索引信息可以快速定位message和确定response的最大大小。
通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。
通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。
关于kafka数据重复消费的问题:
底层原因:已经消费了数据,但是offset没提交。zookeeper上记录的还是上次的offset。
kafka数据丢失的原因:
设置offset为自动提交,当offset提交时,数据还未处理,如果刚好kill掉线程,这部分内存中的数据会丢失。
解决方案:记录offset到本地,对比前后的offset。
如果需要重新消费之前消费过的数据
1.修改offset
2.使用不同的group消费kafka。
开启系统自带zookeeper:./bin/zookeeper-server-start.sh config/zookeeper.properties &
开启自己配置的zookeeper:./bin/zkCli.sh start
开启kafka集群:./bin/kafka-server-start.sh config/server.properties &
创建topic:(创建一个叫做test的topic,只有一个分区,一个副本) ./bin/kafka-topics.sh --create --zookeeper node:2181 --replication-factor 1 --partitions 1 --topic test
查看创建的topic:./bin/kafka-topics.sh --list --zookeeper node:2181
生产者发送消息:./bin/kafka-console-producer.sh --broker-list node:9092 --topic test
aaaaa
消费者获取消息并输出:./bin/kafka-console-consumer.sh --zookeeper node:2181 --topic test --from-beginning
搭建1个多个broker的集群:
cp config/server.properties config/server-1.properties
cp config/server.properties config/server-2.properties
原来的server.properties文件:
broker.id=0
port=9092
log.dir=/.../kafka-logs
修改properties:
server-1.properties:
broker.id=1
port=9093
log.dir=/.../kafka-logs-1
server-2.properties:
broker.id=2
prot=9094
log.dir=/.../kafka-logs-2
创建一个拥有三个副本的topic:
./bin/kafka-topics.sh --create --zookeeper node:2181 --replication-factor 3 --partitions 1 --topic my-replicated-topic
查看节点信息:
./bin/kafka-topics.sh --describe --zookeeper node:2181 --topic my-replicated-topic
Topic:my-replicated-topic PartitionCount:1 ReplicationFactor:3 Configs:
Topic: my-replicated-topic Partition: 0 Leader: 1 Replicas: 1,2,0 Isr: 1,2,0
第一行是对所有分区的一个描述,然后每个分区都会对应一行,因为我们只有一个分区所以下面就只加了一行。
leader:负责处理消息的读和写,leader是从所有节点中随机选择的.
replicas:列出了所有的副本节点,不管节点是否在服务中.
isr:是正在服务中的节点.
使用客户端远程连接kafka的时候记得要保证客户端和服务端的kafka版本一致。不然连接不会成功。(之前在IDEA中尝试使用客户端连接kafka失败,原因是IDEA使用的kafka版本和虚拟机上的kafka版本不一致,导致连接失败)
Consumer Group:
定义了一组消费者。一般来说消息中间件都有两种模式:队列模式和发布订阅模式。队列模式及每一个消息都会给其中一个消费者,而发布订阅模式则是每个消息都广播给所有的消费者。Kafka就是使用了Consumer Group来实现了这两种模式。
如果所有的消费者都是同一个Consumer Group的话,就是队列模式,每个消息都会负载均衡的分配到所有的消费者。
如果所有的消息者都在不同的Consumer Group的话,就是发布订阅模式,每个消费者都会得到这个消息。
下图是一个Topic,配置了4个Patition,分布在2个Broker上。由于有2个Consumer Group,Group A和Group B都可以得到P0-P3的所有消息,是一个订阅发布模式。两个Group中的Consumer则负载均衡的接收了这个Topic的消息。如果Group中的Consumer的总线程数量超过了Partition的数量,则会出现空闲状态。理解:
在kafka中,对于每个topic,可以创建一个或者多个分区和副本。如果在一台机器上想要创建多个broker,那么每个broker的id必须不同,端口号也必须不同,kafka通过broker的id确定唯一的broker。如果不在一台机器上,那么broker还是不能一样,但是端口号可以使用默认的9092.
分区数可以大于broker的数量,但是副本数不能够大于broker的数量.如果每个topic配置的副本数为n,那么集群中允许有n-1个broker不工作,集群还是可以正常运行。
消费者组:
如果消费者配置的group.id一样的话,那么这些消费者属于同一个消费者组。如果消费者在用一个消费者组的话,那是采用的队列模式,每个消息都会负载均衡的分配到所有的消费者,也就是说,对于每个消费者,接收不到完整的生产者发送的消息,只能够接收部分生产者发送的消息,这个消费者组的所有消费者总的接收的消息才是集群中生产者发送的消息。
对于不同的消费者组,之间没有关系,采用的是发布订阅模式,每个消费者组都可以接收到生产者发送的消息,彼此之间互不干扰。
如果一个消费者组只有一个消费者的话,那么这个消费者可以接收到全部的生产者发布的消息。消费者订阅的是某个topic或者几个topic,和topic的分区,副本并没有直接的关系。
生产者:
生产者往topic上发布消息,可以指定发送到哪个分区,需要自定义分区函数。
对于有多个分区的topic,当接收到一条消息的时候,使用默认的分区函数,将消息发送给某个分区(可以自定义分区函数),也就是说,不同的分区,他们之间的数据是不相同的,分区之间也没有顺序可言。但是对于每个独立的分区,分区内的数据是有序的,先到的消息排在前,后到的消息排在后,并且每个分区都维护自己的一个offset。消费者订阅的是topic,也可以指定订阅哪个分区。
kafka的每个分区只能同时被一个消费者消费(一个消费者组内只有一个消费者可以消费这个分区),但是不同的消费者组可以同时消费这个分区。
消费者维护自己的offset。
kafka中删除某个topic的方法:
配置server.properties中delete.topic.enable=true;
删除topic的命令:./bin/kafka-topics.sh --delete --zookeeper node:2181 --topic test
如果topic只是被标记为marked for deletion,还是删除不掉,那么需要删除zookeeper目录下的topic
./bin/zkCli.sh rmr /brokers/topics/test
如果只是标记删除,记得删除zookeeper目录下的文件。
开启kafka服务进程:./bin/kafka-server-start.sh -daemon config/server.properties (添加daemon关键字)
Kafka运行时很少有大量读磁盘的操作,主要是定期批量写磁盘操作,因此操作磁盘很高效。这跟Kafka文件存储中读写message的设计是息息相关的。Kafka中读写message有如下特点:
写message:
消息从java堆转入page cache(即物理内存)。
由异步线程刷盘,消息从page cache刷入磁盘。
读message:
消息直接从page cache转入socket发送出去。
当从page cache没有找到相应数据时,此时会产生磁盘IO,从磁盘Load消息到page cache,然后直接从socket发出去
Kafka高效文件存储设计特点:
Kafka把topic中一个parition大文件分成多个小文件段,通过多个小文件段,就容易定期清除或删除已经消费完文件,减少磁盘占用。
通过索引信息可以快速定位message和确定response的最大大小。
通过index元数据全部映射到memory,可以避免segment file的IO磁盘操作。
通过索引文件稀疏存储,可以大幅降低index文件元数据占用空间大小。
关于kafka数据重复消费的问题:
底层原因:已经消费了数据,但是offset没提交。zookeeper上记录的还是上次的offset。
kafka数据丢失的原因:
设置offset为自动提交,当offset提交时,数据还未处理,如果刚好kill掉线程,这部分内存中的数据会丢失。
解决方案:记录offset到本地,对比前后的offset。
如果需要重新消费之前消费过的数据
1.修改offset
2.使用不同的group消费kafka。