文章目录
- 前言
- 关于Kafka&ZooKeeper
- 关于__consumer_offsets
- 解决办法
前言
我们在启动 Kafka 集群服务时,通过 jps 命令查不到 kafka 服务进程。或者在 Kafka 集群中创建 topic 时,报错replication factor: 1 larger than available brokers: 0
。都是由于 Kafka 服务无法启动或者启动后自动关闭导致的。
- 可先尝试使用守护进程模式启动 Kafka:kafka-server-start.sh
-daemon
config/server.properties - 首先检查一下所有节点的 ZooKeeper 服务是否可以正常启动,尤其是
myid
的配置千万不能一样。 - 然后检查一下 Kafka 的配置文件
server.properties
。第一个配置参数,每个 Kafka 节点的broker.id
不能相同。第二个配置参数,通过 ZooKeeper 连接 Kafka 集群需要在localhost:port
后面加上/kafka
,并且在创建 topic 时也需要加上:kafka-topics.sh --create --topic sgapp122_log --zookeeper master01:2181/kafka --partitions 3 --replication-factor 2
[root@master01 ~]# cd /opt/software/spark/kafka241/config
[root@master01 config]# vi server.properties
关于Kafka&ZooKeeper
- 由于 Kafka 依赖于 ZooKeeper,启动后要去 ZooKeeper 中注册。因此开启服务的时候,是先开 ZooKeeper 后开 Kafka,而关闭服务的时候,是先关 Kafka 后关 ZooKeeper。注意这里 Kafka 关闭服务的时间较长,如果还未等到集群中的 Kafka 全部关闭,就去关闭 ZooKeeper,或者是先关了 ZooKeeper再关 Kafka,则有可能引发下次 Kafka 启动后自动关闭的问题。这是因为 Kafka 在退出服务的时候,会把 ZooKeeper 下的
/kafka/brokers/ids
里的临时节点删掉,但如果是 ZooKeeper 先退出就不会删除。当下次启动时,Kafka 再用 id 去注册,发现已经存在了,所以会导致启动失败。
关于__consumer_offsets
- 由于 ZooKeeper 并不适合大批量的频繁写入操作,新版 Kafka 将
consumer
的位移信息保存在 Kafka 内部的topic
中,即__consumer_offsets topic
,并且默认提供了kafka_consumer_groups.sh
脚本供用户查看consumer
的信息。 -
__consumer_offsets
作为 Kafka 的内部 topic,用来保存消费组元数据以及对应提交的offset
信息。每次消费者消费完一批数据需要标记这批数据被消费掉时,需要将消费的偏移量即offset
提交掉,这个提交过程其实就是将offset
信息写入__consumer_offsets
的过程。 - 一般情况下,当集群中第一次有消费者拉取数据时会自动创建
__consumer_offsets
。首先在offsets.topic.replication.factor
配置的值(副本因子,默认值为1)和当前可用的 brokers 个数中取最小值作为__consumer_offsets
的副本数,offsets.topic.num.partitions
作为分区数(默认值为50),然后创建__consumer_offsets
。 - 考虑到一个 Kafka 生产环境中可能有很多
consumer
和consumer group
,如果这些consumer
同时拉去数据并提交offset
,必将加重__consumer_offsets
的写入负载,因此 Kafka 默认为该topic
创建了50
个分区,并且对每个group.id
做哈希求模运算Math.abs(groupID.hashCode()) % numPartitions
,从而将负载分散到不同的__consumer_offsets
分区上。 __consumer_offsets
的每条消息可以看成是K/V格式的消息,其中 key 就是一个三元组:group.id+topic+partition
,而 value 就是offset
的值。
解决办法
- 找到 ZooKeeper 根目录下,用来存放
myid
文件的文件夹mydata
,这个是自己创建的,可能名字会不同。进入mydata
之后,删除文件夹version-2
。可以把所有节点的都删除,下次启动时会自动创建。
[root@master01 ~]# cd /opt/software/hadoop/zookeeper357/mydata
[root@master01 mydata]# ls
myid version-2
[root@master01 mydata]# rm -rf version-2
- 重新建立索引:找到Kafka根目录下,用来存放日志文件的文件夹
kfklogs
,对应的是配置文件server.properties
里的log.dirs=/opt/software/spark/kafka241/kfklogs
,这个也是自己创建的,名字可能会不同。将所有节点的日志文件夹kfklogs
删除重新创建。
[root@master01 ~]# cd /opt/software/spark/kafka241/
[root@master01 kafka241]# ls
bin config kfklogs libs LICENSE logs NOTICE site-docs
[root@master01 kafka241]# rm -rf kfklogs
[root@master01 kafka241]# mkdir kfklogs
- 删除brokers:进入 ZooKeeper 客户端删除 Kafka。集群所有节点的 ZooKeeper 服务都需要启动,删除操作只需在一个节点上操作即可。
[root@master01 ~]# zkCli.sh
[zk: localhost:2181(CONNECTED) 0] ls /
[kafka,zookeeper]
[zk: localhost:2181(CONNECTED) 1] deleteall /kafka
- 最后关闭 ZooKeeper 重启,再开启 Kafka。