Kafka2.13-3.3.2 安装部署+最后报错处理全过程(CentOS 7 虚拟机)

目录

  • 查看环境,寻找安装包
  • 安装和部署
    • 一、提前确认
    • 二、解压并更名
    • [三、建数据 / 日志目录](#三、建数据 / 日志目录)
    • [四、Zookeeper 单节点配置](#四、Zookeeper 单节点配置)
    • [五、准备 3 份 broker 配置](#五、准备 3 份 broker 配置)
    • 六、创建并启动脚本(一次性复制即可用)
      • [① 一键生成启动脚本(包含全部内容)](#① 一键生成启动脚本(包含全部内容))
      • [② 赋可执行权限](#② 赋可执行权限)
      • [③ 运行脚本](#③ 运行脚本)
      • [④ 验证是否都起来了](#④ 验证是否都起来了)
        *
        • [有偏差:你只看到 1 个 Kafka 进程,说明 3 个 broker 并没有全部成功启动(后面有我的解决和修改过程可以直接跳过,你也可以在这里逐步排查,可能问题不一样)](#有偏差:你只看到 1 个 Kafka 进程,说明 3 个 broker 并没有全部成功启动(后面有我的解决和修改过程可以直接跳过,你也可以在这里逐步排查,可能问题不一样))
      • 下面是我的解决过程梳理和总结
    • [七、 一键关闭(可选备用脚本)](#七、 一键关闭(可选备用脚本))
    • 八、开机自启(可选)
      • [① 创建 systemd 服务文件](#① 创建 systemd 服务文件)
      • [② 创建对应的 stop 脚本(如果还没有)](#② 创建对应的 stop 脚本(如果还没有))
      • [③ 重载并设为开机自启](#③ 重载并设为开机自启)
      • [④ 验证](#④ 验证)
      • ⑤慎重验证
      • 这里我报错:
    • 快速修复:
      *
      • [① 第一次现象:只有 1 个 Kafka](#① 第一次现象:只有 1 个 Kafka)
      • [② 立即查看 3 份日志尾](#② 立即查看 3 份日志尾)
      • [③ 前台启动 2 号 broker,现场报错](#③ 前台启动 2 号 broker,现场报错)
      • [④ 确认 9092 被谁占用](#④ 确认 9092 被谁占用)
      • [⑤杀掉旧进程 & 清理锁文件](#⑤杀掉旧进程 & 清理锁文件)
      • [⑥ 把 3 份配置端口改成不冲突的 9191/9192/9193](#⑥ 把 3 份配置端口改成不冲突的 9191/9192/9193)
      • [⑦ 写死 JAVA_HOME 到所有 systemd 单元](#⑦ 写死 JAVA_HOME 到所有 systemd 单元)
      • [⑧ 一键创建 4 个独立 systemd 单元(复制即用)](#⑧ 一键创建 4 个独立 systemd 单元(复制即用))
        • [8.1 Zookeeper](#8.1 Zookeeper)
        • [8.2 3 个 Kafka broker](#8.2 3 个 Kafka broker)
      • [⑨ 重载 & 自启](#⑨ 重载 & 自启)
      • [⑩ 最终验证](#⑩ 最终验证)
      • 最后这里成功!!!
        • [⑪ 重启整机测试(可选)](#⑪ 重启整机测试(可选))

查看环境,寻找安装包

官网寻找安装包

  1. 打开官方"存档"页面

    3.3 系列已从首页的 Supported 区域下架,进入了 Archived releases

    直接访问:https://kafka.apache.org/downloads

    在页面最下方 "Archived releases" 区域即可看到

    复制代码
    3.3.2
    3.3.1
    3.3.0

    任选其一即可下载,例如:

    复制代码
    kafka_2.13-3.3.2.tgz  (asc, sha512)
  2. 校验文件(官方唯一验证方法)

    ① 下载同名的 .sha512 文件

    bash 复制代码
    wget https://archive.apache.org/dist/kafka/3.3.2/kafka_2.13-3.3.2.tgz.sha512

    ② Linux/Mac 终端执行

    bash 复制代码
    sha512sum -c kafka_2.13-3.3.2.tgz.sha512

    输出 OK 即通过验证。

附:官方 3.3 文档固定入口
https://kafka.apache.org/33/documentation.html

版本选择,要求高可用

一句话结论
只用 3.3.2(Scala 2.13 版) ,不要再纠结 3.3.0/3.3.1;单机 CentOS 7 也能跑"伪分布式三副本",只是三副本≠高可用------一台虚拟机挂了所有副本一起挂。下面给你完整可落地的"单机 3.3.2 三副本"步骤,先跑通,再考虑以后多机扩展。


一、3.3.2 为什么更合适

  1. 3.3.2 是 3.3 线的最后一个补丁版,修掉 20 个 bug(含潜在数据丢失/稳定性问题)。
  2. Scala 2.13 比 2.12 体积小一点点,官方也写 "建议使用 2.13"
  3. 以后真要扩容到多机,同一版本直接复制配置即可,避免混版本。

二、CentOS 7 单机跑"伪分布式 3 副本"思路

  • 用同一台机器开 3 个 Kafka 进程 ,每个进程一个 broker.id 和独立端口/目录,Zookeeper 仍用同一实例。
  • 只能验证功能/调试用,真正高可用必须 ≥3 台物理机。

三、10 分钟落地步骤

  1. 前置依赖

    bash 复制代码
    sudo yum install -y java-11-openjdk-devel wget
    java -version   # 确认 11+
  2. 目录规划

    bash 复制代码
    sudo mkdir -p /opt/kafka-cluster
    cd /opt/kafka-cluster
  3. 下载并解压 3.3.2

    bash 复制代码
    wget https://archive.apache.org/dist/kafka/3.3.2/kafka_2.13-3.3.2.tgz
    tar -xzf kafka_2.13-3.3.2.tgz
    mv kafka_2.13-3.3.2 kafka
    # 建 3 份配置
    cp -r kafka kafka-1 kafka-2 kafka-3
  4. 起 Zookeeper(单节点)

    bash 复制代码
    # 用自带脚本即可
    nohup kafka/bin/zookeeper-server-start.sh kafka/config/zookeeper.properties > zk.log 2>&1 &
  5. 为 3 个 broker 准备配置文件

    把下面三段分别写进 kafka-1/config/server.propertieskafka-2/config/server.propertieskafka-3/config/server.properties,只改差异项:

    配置项 broker 1 broker 2 broker 3
    broker.id 1 2 3
    listeners PLAINTEXT://:9092 PLAINTEXT://:9093 PLAINTEXT://:9094
    log.dirs /tmp/kafka-logs-1 /tmp/kafka-logs-2 /tmp/kafka-logs-3
    zookeeper.connect localhost:2181 localhost:2181 localhost:2181

    其余保持默认即可。

  6. 启动 3 个 broker

    bash 复制代码
    nohup kafka-1/bin/kafka-server-start.sh kafka-1/config/server.properties > k1.log 2>&1 &
    nohup kafka-2/bin/kafka-server-start.sh kafka-2/config/server.properties > k2.log 2>&1 &
    nohup kafka-3/bin/kafka-server-start.sh kafka-3/config/server.properties > k3.log 2>&1 &
  7. 验证 3 副本 topic

    bash 复制代码
    # 建 topic,3 副本 3 分区
    kafka/bin/kafka-topics.sh --create --topic test-ha \
      --bootstrap-server localhost:9092 \
      --partitions 3 --replication-factor 3
    
    # 查看分区分布
    kafka/bin/kafka-topics.sh --describe --topic test-ha --bootstrap-server localhost:9092

    应当看到每个分区都有 Leader, Replicas: 1,2,3, Isr: 1,2,3

  8. 简单生产/消费测试

    bash 复制代码
    # 生产
    kafka/bin/kafka-console-producer.sh --topic test-ha --bootstrap-server localhost:9092
    # 消费
    kafka/bin/kafka-console-consumer.sh --topic test-ha --bootstrap-server localhost:9092 --from-beginning

四、单机"三副本"的局限

  • 高可用:❌ 一台机器挂了,三个进程一起死。
  • 功能验证:✅ 可以跑通多副本、Leader 切换、ISR 列表变化。
  • 后续扩容:把配置里的 listeners 改成各自主机名/IP,log.dirs 换成独立磁盘即可。

一句话总结
下载 kafka_2.13-3.3.2.tgz,单机起 3 个 broker 就能跑 3 副本测试;真正高可用还需再加两台机器。

注:/usr/local 是给"本地手工编译 "或"包管理器之外的系统级软件 "留的;Kafka 官方只提供二进制压缩包,解压即用,既不属于系统自带,也不走 make install,所以社区习惯放到 /opt专门放大型第三方独立软件),避免日后系统升级或包管理器误碰。

安装和部署

下面给你一份面向 CentOS 7、虚拟机单机 的"一行不落"复制粘贴教程。

目标目录:/opt/kafka3.3.2

源包路径:/root/kafka_2.13-3.3.2.tgz


一、提前确认

bash 复制代码
java -version   # 需 11 以上

#输出
[root@localhost redis6.2.14]# java -version
java version "17.0.15" 2025-04-15 LTS
Java(TM) SE Runtime Environment (build 17.0.15+9-LTS-241)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.15+9-LTS-241, mixed mode, sharing)
[root@localhost redis6.2.14]#

二、解压并更名

bash 复制代码
sudo mkdir -p /opt/kafka3.3.2
sudo tar -xzf /root/kafka_2.13-3.3.2.tgz -C /opt/kafka3.3.2 --strip-components=1

解压后目录结构应为:
/opt/kafka3.3.2/bin
/opt/kafka3.3.2/config

...


三、建数据 / 日志目录

bash 复制代码
sudo mkdir -p /opt/kafka3.3.2/data/zookeeper
sudo mkdir -p /opt/kafka3.3.2/data/kafka-logs-1 \
               /opt/kafka3.3.2/data/kafka-logs-2 \
               /opt/kafka3.3.2/data/kafka-logs-3
sudo chown -R $USER:$USER /opt/kafka3.3.2

四、Zookeeper 单节点配置

bash 复制代码
cp /opt/kafka3.3.2/config/zookeeper.properties /opt/kafka3.3.2/config/zookeeper.properties.bak

编辑 /opt/kafka3.3.2/config/zookeeper.properties 只改两项(其余默认):

复制代码
dataDir=/opt/kafka3.3.2/data/zookeeper
clientPort=2181

五、准备 3 份 broker 配置

bash 复制代码
for i in 1 2 3; do
  cp /opt/kafka3.3.2/config/server.properties /opt/kafka3.3.2/config/server-$i.properties
done

分别编辑 3 个文件,只改以下 4 行(操作在之后代码块):

文件 broker.id listeners log.dirs advertised.listeners
server-1.properties 1 PLAINTEXT://:9092 /opt/kafka3.3.2/data/kafka-logs-1 PLAINTEXT://localhost:9092
server-2.properties 2 PLAINTEXT://:9093 /opt/kafka3.3.2/data/kafka-logs-2 PLAINTEXT://localhost:9093
server-3.properties 3 PLAINTEXT://:9094 /opt/kafka3.3.2/data/kafka-logs-3 PLAINTEXT://localhost:9094

其余保持默认(尤其 zookeeper.connect=localhost:2181)。

不需要手动打开图形编辑器。

用一条 sed 或 echo 命令就能一次改好,下面给出复制即用的三行脚本,把 4 个关键配置一次性写入对应文件:

下面给出一次可直接复制/粘贴的 修正版脚本,并逐条指出与旧脚本的区别。


可直接执行的脚本(已修复换行/引号问题)

bash 复制代码
# 1 号 broker
sed -ri \
  -e 's/^broker.id=.*/broker.id=1/' \
  -e 's|^listeners[[:space:]]*=.*|listeners=PLAINTEXT://:9092|' \
  -e 's|^log.dirs[[:space:]]*=.*|log.dirs=/opt/kafka3.3.2/data/kafka-logs-1|' \
  -e 's|^#?advertised.listeners[[:space:]]*=.*|advertised.listeners=PLAINTEXT://localhost:9092|' \
  /opt/kafka3.3.2/config/server-1.properties

# 2 号 broker
sed -ri \
  -e 's/^broker.id=.*/broker.id=2/' \
  -e 's|^listeners[[:space:]]*=.*|listeners=PLAINTEXT://:9093|' \
  -e 's|^log.dirs[[:space:]]*=.*|log.dirs=/opt/kafka3.3.2/data/kafka-logs-2|' \
  -e 's|^#?advertised.listeners[[:space:]]*=.*|advertised.listeners=PLAINTEXT://localhost:9093|' \
  /opt/kafka3.3.2/config/server-2.properties

# 3 号 broker
sed -ri \
  -e 's/^broker.id=.*/broker.id=3/' \
  -e 's|^listeners[[:space:]]*=.*|listeners=PLAINTEXT://:9094|' \
  -e 's|^log.dirs[[:space:]]*=.*|log.dirs=/opt/kafka3.3.2/data/kafka-logs-3|' \
  -e 's|^#?advertised.listeners[[:space:]]*=.*|advertised.listeners=PLAINTEXT://localhost:9094|' \
  /opt/kafka3.3.2/config/server-3.properties

与旧脚本的区别逐条说明(注意之前的报错,因为出现转义字符的问题,上面代码已经修改过。)

序号 旧问题 修正做法 说明
1 单引号里跨行反斜杠续行 直接拆成 多段 -e 表达式 避免 sed 报 "未终止的正则"
2 分隔符 / 与路径 /opt/... 冲突 统一用 ` ` 作分隔符
3 正则 ^listeners=.* 可能匹配不到空格 写成 ^listeners[[:space:]]*= 兼容 key=valuekey = value
4 只处理 #advertised.listeners 的注释行 改成 #? 同时匹配已取消注释或仍注释的行
5 -r 扩展正则 -r(GNU sed) ?、`

把上面脚本一次性粘进终端即可,无需再手工编辑。

执行完后,三份配置就全部改好,无需再打开任何编辑器。


六、创建并启动脚本(一次性复制即可用)

​ 下面给你一条命令一条命令的「复制-粘贴」版完整步骤,连脚本内容都帮你一次性生成,不用手写,跟着敲即可。


① 一键生成启动脚本(包含全部内容)

bash 复制代码
cat > ~/start-kafka.sh <<'EOF'  #这一步直接是创建脚本,就是把下面的代码保存成脚本'~/start-kafka.sh'
#!/bin/bash
# 启动 Zookeeper
nohup /opt/kafka3.3.2/bin/zookeeper-server-start.sh \
  -daemon /opt/kafka3.3.2/config/zookeeper.properties \
  > /opt/kafka3.3.2/zk.log 2>&1 &

sleep 5   # 等 Zookeeper 完全起来

# 启动 3 个 broker
for i in 1 2 3; do
  nohup /opt/kafka3.3.2/bin/kafka-server-start.sh \
    -daemon /opt/kafka3.3.2/config/server-$i.properties \
    > /opt/kafka3.3.2/broker-$i.log 2>&1 &
done

echo "Zookeeper + 3 brokers started. Logs under /opt/kafka3.3.2/"
EOF

② 赋可执行权限

bash 复制代码
chmod +x ~/start-kafka.sh

③ 运行脚本

bash 复制代码
~/start-kafka.sh

#运行结果
Zookeeper + 3 brokers started. Logs under /opt/kafka3.3.2/#

④ 验证是否都起来了

bash 复制代码
jps | egrep 'QuorumPeerMain|Kafka'

应看到 1 个 QuorumPeerMain(Zookeeper)+ 3 个 Kafka 进程。

bash 复制代码
#运行结果(有偏差)
27940 Kafka
26891 QuorumPeerMain
有偏差:你只看到 1 个 Kafka 进程,说明 3 个 broker 并没有全部成功启动(后面有我的解决和修改过程可以直接跳过,你也可以在这里逐步排查,可能问题不一样)

你只看到 1 个 Kafka 进程,说明 3 个 broker 并没有全部成功启动。

按下面 3 步排查并一次性修复:


  1. 立即查日志定位原因 ,然后这里我的是空目录
bash 复制代码
# 看看每个 broker 日志末尾 20 行
tail -n 20 /opt/kafka3.3.2/broker-*.log

常见报错:端口被占用、目录权限不足、log.dirs 不存在、JMX 端口冲突等。


  1. 一键补齐缺失目录 & 权限
bash 复制代码
mkdir -p /opt/kafka3.3.2/data/{kafka-logs-1,kafka-logs-2,kafka-logs-3}
chown -R $(whoami):$(whoami) /opt/kafka3.3.2

  1. 先停后启(干净重启)
bash 复制代码
# 如果还有残存进程
pkill -f 'kafka\.Kafka'    # 杀 Kafka
pkill -f QuorumPeerMain    # 杀 Zookeeper

# 重新启动
~/start-kafka.sh

# 再验证
sleep 5
jps | egrep 'QuorumPeerMain|Kafka'

正常应看到 1 个 QuorumPeerMain + 3 个 Kafka


如果日志里出现 "Address already in use"

说明 9092/9093/9094 端口被系统占用,改脚本里的端口即可;

如果日志里出现 "No space left on device"权限 denied,就回到第 2 步继续修正目录/权限。


下面是我的解决过程梳理和总结

【一句话总结错误原因】
"9092 被旧 broker 死死占着,导致 2、3 号 broker 起不来;把旧进程杀掉、把 3 台 broker 端口一次性改成 9191/9192/9193,再清掉 .lock 文件,就彻底 OK。"


1、完整报错链路(按时间线)
时间 现象 根因 日志关键行
T0 jps 只有 1 个 Kafka 2、3 号没起来 ---
T1 broker-2.log 报错 端口 9092 被占用 Socket server failed to bind to 0.0.0.0:9092: 地址已在使用
T2 ls -l /opt/kafka3.3.2/data 目录缺 log.dirs 没提前建 ---
T3 .lock 已存在 旧进程没停干净 Failed to acquire lock on file .lock

2、修复步骤(复制即用)
  1. 杀干净所有残留进程
bash 复制代码
pkill -9 -f 'kafka\.Kafka'
pkill -f QuorumPeerMain
  1. 一次性建目录 + 删 .lock
bash 复制代码
mkdir -p /opt/kafka3.3.2/data/{kafka-logs-1,kafka-logs-2,kafka-logs-3}
chown -R $(whoami):$(whoami) /opt/kafka3.3.2/data
for i in 1 2 3; do rm -f /opt/kafka3.3.2/data/kafka-logs-$i/.lock; done
  1. 把 3 份配置端口全部改成 9191/9192/9193
bash 复制代码
for i in 1 2 3; do
  port=$((9190+i))
  cfg="/opt/kafka3.3.2/config/server-$i.properties"
  sed -ri \
    -e "s#^listeners[[:space:]]*=.*#listeners=PLAINTEXT://:${port}#" \
    -e "s#^advertised.listeners[[:space:]]*=.*#advertised.listeners=PLAINTEXT://localhost:${port}#" \
    -e "s#^broker.id[[:space:]]*=.*#broker.id=$i#" \
    "$cfg"
done
  1. 启动并验证
bash 复制代码
~/start-kafka.sh
sleep 5 && jps | egrep 'QuorumPeerMain|Kafka'

实际输出结果,终于成功:

bash 复制代码
[root@localhost ~]# ~/start-kafka.sh

Zookeeper + 3 brokers started. Logs under /opt/kafka3.3.2/
[root@localhost ~]# sleep 5 && jps | egrep 'QuorumPeerMain|Kafka'

36151 Kafka
36152 Kafka
36186 Kafka
26891 QuorumPeerMain
30317 Kafka
[root@localhost ~]# 
[root@localhost ~]# ss -lntup | grep :9092
tcp    LISTEN     0      50     [::]:9092               [::]:*                   users:(("java",pid=30317,fd=125))
[root@localhost ~]# # 会看到 PID 30317
[root@localhost ~]# kill -9 30317
[root@localhost ~]# sleep 2 && jps | egrep 'QuorumPeerMain|Kafka'
26891 QuorumPeerMain
[root@localhost ~]# for p in 9191 9192 9193; do echo "== $p =="; ss -lntup | grep ":$p"; done
== 9191 ==
== 9192 ==
== 9193 ==
  1. 确认 9092 已释放
bash 复制代码
ss -lntup | grep :9092   # 应无结果

3、后续不再踩坑的 3 条建议
  1. 永远先杀干净旧进程再启动新配置。
  2. 端口批量错开(如 9191/9192/9193),避免手动改漏。
  3. 日志为空或报错时立即 tail -n 30,定位关键字只用 10 秒。

七、 一键关闭(可选备用脚本)

如果想一次性关闭,再做一个 ~/stop-kafka.sh

bash 复制代码
cat > ~/stop-kafka.sh <<'EOF'
#!/bin/bash
# 依次关闭 3 个 broker
for i in 1 2 3; do
  /opt/kafka3.3.2/bin/kafka-server-stop.sh /opt/kafka3.3.2/config/server-$i.properties
done
# 关闭 Zookeeper
/opt/kafka3.3.2/bin/zookeeper-server-stop.sh /opt/kafka3.3.2/config/zookeeper.properties
echo "All stopped."
EOF
#赋权
chmod +x ~/stop-kafka.sh

全部完成,直接复制即可。


​ 验证

bash 复制代码
# 建 topic(3 分区 3 副本)
/opt/kafka3.3.2/bin/kafka-topics.sh --create --topic test-ha \
  --bootstrap-server localhost:9092 --partitions 3 --replication-factor 3

# 查看
/opt/kafka3.3.2/bin/kafka-topics.sh --describe --topic test-ha --bootstrap-server localhost:9092

看到每个分区 Replicas: 1,2,3Isr: 1,2,3 即成功。


八、开机自启(可选)

下面给出 CentOS 7 systemd 一键方案 ,复制即可用。

完成后执行 systemctl enable --now kafka 就能开机自启 + 立即启动。


① 创建 systemd 服务文件

bash 复制代码
sudo tee /etc/systemd/system/kafka.service >/dev/null <<'EOF'
[Unit]
Description=Kafka 3.3.2 Cluster (3 brokers)
After=network.target

[Service]
Type=forking
User=root
ExecStart=/root/start-kafka.sh
ExecStop=/root/stop-kafka.sh
RemainAfterExit=yes
TimeoutStartSec=60
TimeoutStopSec=30

[Install]
WantedBy=multi-user.target
EOF

② 创建对应的 stop 脚本(如果还没有)

bash 复制代码
sudo tee /root/stop-kafka.sh >/dev/null <<'EOF'
#!/bin/bash
# 依次停 3 个 broker
for i in 1 2 3; do
  /opt/kafka3.3.2/bin/kafka-server-stop.sh
done
# 停 Zookeeper
/opt/kafka3.3.2/bin/zookeeper-server-stop.sh
EOF
sudo chmod +x /root/stop-kafka.sh

③ 重载并设为开机自启

bash 复制代码
sudo systemctl daemon-reload
sudo systemctl enable --now kafka

④ 验证

bash 复制代码
#一般检查到这一步就可以,出现active就成功,不用之后的重启
systemctl status kafka

⑤慎重验证

bash 复制代码
# 重启后自动拉起,该命令用于重启整个Linux服务器就是整个机器!!慎用!!!
sudo reboot
# 登录后检查,jps用来列出所有java进程和主类名,后面用来确定Zookeeper和Kafka boker是否正常执行
jps | egrep 'QuorumPeerMain|Kafka'

看到 1 个 QuorumPeerMain + 3 个 Kafka 即成功。


这里我报错:

  • systemctl status kafka 显示 active (exited) ,说明 systemd 认为 start-kafka.sh 已经执行完成并退出 ,但 它不负责守护进程

  • jps看不到任何 Zookeeper/Kafka 进程3 个 broker 并没有真正跑起来

  • 根本原因
    start-kafka.sh 里用了 nohup ... & 把进程放到后台,systemd 默认 Type=forking 需要主进程长期存活,而你的脚本瞬间结束,systemd 就认为服务已经"成功退出"。

  • 问题概述:start-kafka.sh 依旧是 "瞬间结束" 的脚本------它把 Zookeeper 和 3 个 Kafka 丢到后台 就退出了,systemd(Type=simple)发现主进程退出,于是立即执行 ExecStop,然后整服务标记为 failed

    解决思路:让 systemd 直接托管 Zookeeper + 3 个 Kafka,而不是托管一个"启动脚本"。最简做法是把它们拆成 4 个独立 service (1 Zookeeper + 3 Kafka),相互依赖即可。下面给出 "一条龙" 方案,复制即用。

  • 之后又所有服务都报 status=127 ------ 典型"找不到可执行文件或脚本"错误。

    90% 是 路径写错没给执行权限 。原因是:1.JDK 不在 PATH (systemd 环境变量 ≠ 登录 shell)2.配置里缺 JAVA_HOME

    解决办法为下面的⑦,然后成功

快速修复:

下面是一份**"问题-定位-修复"** 的完整复盘,完全保留你运行过的每一个代码块 ,方便你后续直接复制使用或给团队做文档。

⏩ 从 第一次只看到 1 个 Kafka 开始,直到 真正 4 个进程常驻并成功开机自启


① 第一次现象:只有 1 个 Kafka
bash 复制代码
[root@localhost ~]# jps | egrep 'QuorumPeerMain|Kafka'
27940 Kafka
26891 QuorumPeerMain

② 立即查看 3 份日志尾
bash 复制代码
[root@localhost ~]# tail -n 20 /opt/kafka3.3.2/broker-*.log
==> /opt/kafka3.3.2/broker-1.log <==

==> /opt/kafka3.3.2/broker-2.log <==

==> /opt/kafka3.3.2/broker-3.log <==

日志为空 → 说明根本没成功启动。


③ 前台启动 2 号 broker,现场报错
bash 复制代码
# 先停干净
pkill -f 'kafka\.Kafka'
pkill -f QuorumPeerMain

# 前台跑 2 号
/opt/kafka3.3.2/bin/kafka-server-start.sh /opt/kafka3.3.2/config/server-2.properties

输出核心报错:

复制代码
Socket server failed to bind to 0.0.0.0:9092: 地址已在使用.

④ 确认 9092 被谁占用
bash 复制代码
[root@localhost ~]# ss -lntup|grep 9092
tcp    LISTEN     0      50     [::]:9092               [::]:*                   users:(("java",pid=27940,fd=125))

⑤杀掉旧进程 & 清理锁文件
bash 复制代码
# 杀掉所有残留
pkill -9 -f 'kafka\.Kafka'

# 清理 .lock
for i in 1 2 3; do
  rm -f /opt/kafka3.3.2/data/kafka-logs-$i/.lock
done

⑥ 把 3 份配置端口改成不冲突的 9191/9192/9193
bash 复制代码
for i in 1 2 3; do
  port=$((9190+i))
  cfg="/opt/kafka3.3.2/config/server-$i.properties"
  sed -ri \
    -e "s#^listeners[[:space:]]*=.*#listeners=PLAINTEXT://:${port}#" \
    -e "s#^advertised.listeners[[:space:]]*=.*#advertised.listeners=PLAINTEXT://localhost:${port}#" \
    -e "s#^broker.id[[:space:]]*=.*#broker.id=$i#" \
    "$cfg"
done

⑦ 写死 JAVA_HOME 到所有 systemd 单元
bash 复制代码
# 查出 JDK 路径
[root@localhost ~]# readlink -f $(which java)
/usr/local/jdk17/bin/java

# 写入环境变量
for f in /etc/systemd/system/{zookeeper,kafka-{1..3}}.service; do
  sudo sed -i '/\[Service\]/a Environment=JAVA_HOME=/usr/local/jdk17' "$f"
done

⑧ 一键创建 4 个独立 systemd 单元(复制即用)
8.1 Zookeeper
bash 复制代码
sudo tee /etc/systemd/system/zookeeper.service >/dev/null <<'EOF'
[Unit]
Description=Zookeeper for Kafka
After=network.target

[Service]
Type=simple
User=root
ExecStart=/opt/kafka3.3.2/bin/zookeeper-server-start.sh /opt/kafka3.3.2/config/zookeeper.properties
ExecStop=/opt/kafka3.3.2/bin/zookeeper-server-stop.sh
Environment=JAVA_HOME=/usr/local/jdk17
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
8.2 3 个 Kafka broker
bash 复制代码
for i in 1 2 3; do
port=$((9190+i))
sudo tee /etc/systemd/system/kafka-${i}.service >/dev/null <<EOF
[Unit]
Description=Kafka Broker ${i}
After=zookeeper.service
Requires=zookeeper.service

[Service]
Type=simple
User=root
ExecStart=/opt/kafka3.3.2/bin/kafka-server-start.sh /opt/kafka3.3.2/config/server-${i}.properties
ExecStop=/opt/kafka3.3.2/bin/kafka-server-stop.sh
Environment=JAVA_HOME=/usr/local/jdk17
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF
done

⑨ 重载 & 自启
bash 复制代码
sudo systemctl daemon-reload
sudo systemctl enable --now zookeeper
for i in 1 2 3; do
  sudo systemctl enable --now kafka-${i}
done

⑩ 最终验证
bash 复制代码
[root@localhost ~]# systemctl status zookeeper kafka-{1..3}
# 四条均显示 active (running)

[root@localhost ~]# jps | egrep 'QuorumPeerMain|Kafka'
12288 Kafka
12289 Kafka
12286 QuorumPeerMain
12287 Kafka

最后这里成功!!!

bash 复制代码
[root@localhost ~]# ls -l /opt/kafka3.3.2/bin/zookeeper-server-start.sh
-rwxr-xr-x. 1 root root 1393 12月 22 2022 /opt/kafka3.3.2/bin/zookeeper-server-start.sh
[root@localhost ~]# ls -l /opt/kafka3.3.2/bin/kafka-server-start.sh
-rwxr-xr-x. 1 root root 1376 12月 22 2022 /opt/kafka3.3.2/bin/kafka-server-start.sh
[root@localhost ~]# readlink -f $(which java)
/usr/local/jdk17/bin/java
[root@localhost ~]# for f in /etc/systemd/system/{zookeeper,kafka-{1..3}}.service; do
>   sudo sed -i '/\[Service\]/a Environment=JAVA_HOME=/usr/local/jdk17' "$f"
> done
[root@localhost ~]# sudo systemctl daemon-reload
[root@localhost ~]# sudo systemctl restart zookeeper kafka-{1..3}
[root@localhost ~]# systemctl status zookeeper kafka-{1..3}
● zookeeper.service - Zookeeper for Kafka
   Loaded: loaded (/etc/systemd/system/zookeeper.service; enabled; vendor preset: disabled)
   Active: active (running) since 三 2025-08-13 11:49:54 CST; 5s ago
 Main PID: 12286 (java)
   CGroup: /system.slice/zookeeper.service
           └─12286 /usr/local/jdk17/bin/java -Xmx512M -Xms512M -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djav...

8月 13 11:49:58 localhost.localdomain zookeeper-server-start.sh[12286]: [2025-08-13 11:49:58,318] INFO The digest value is empty in snapshot (org.apache.zookeeper.server.DataTree)
8月 13 11:49:58 localhost.localdomain zookeeper-server-start.sh[12286]: [2025-08-13 11:49:58,435] INFO ZooKeeper audit is disabled. (org.apache.zookeeper.audit.ZKAuditProvider)
8月 13 11:49:58 localhost.localdomain zookeeper-server-start.sh[12286]: [2025-08-13 11:49:58,448] INFO 325 txns loaded in 64 ms (org.apache.zookeeper.server.persistence.FileTxnSnapLog)
8月 13 11:49:58 localhost.localdomain zookeeper-server-start.sh[12286]: [2025-08-13 11:49:58,448] INFO Snapshot loaded in 214 ms, highest zxid is 0x145, digest is 44971706807 (org.apache.zookeep...ZKDatabase)
8月 13 11:49:58 localhost.localdomain zookeeper-server-start.sh[12286]: [2025-08-13 11:49:58,448] INFO Snapshotting: 0x145 to /tmp/zookeeper/version-2/snapshot.145 (org.apache.zookeeper.server.p...TxnSnapLog)
8月 13 11:49:58 localhost.localdomain zookeeper-server-start.sh[12286]: [2025-08-13 11:49:58,449] INFO Snapshot taken in 1 ms (org.apache.zookeeper.server.ZooKeeperServer)
8月 13 11:49:58 localhost.localdomain zookeeper-server-start.sh[12286]: [2025-08-13 11:49:58,507] INFO zookeeper.request_throttler.shutdownTimeout = 10000 (org.apache.zookeeper.server.RequestThrottler)
8月 13 11:49:58 localhost.localdomain zookeeper-server-start.sh[12286]: [2025-08-13 11:49:58,510] INFO PrepRequestProcessor (sid:0) started, reconfigEnabled=false (org.apache.zookeeper.server.Pr...tProcessor)
8月 13 11:49:58 localhost.localdomain zookeeper-server-start.sh[12286]: [2025-08-13 11:49:58,636] INFO Using checkIntervalMs=60000 maxPerMinute=10000 maxNeverUsedIntervalMs=0 (org.apache.zookeep...nerManager)
8月 13 11:49:59 localhost.localdomain zookeeper-server-start.sh[12286]: [2025-08-13 11:49:59,471] INFO Creating new log file: log.146 (org.apache.zookeeper.server.persistence.FileTxnLog)

● kafka-1.service - Kafka Broker 1
   Loaded: loaded (/etc/systemd/system/kafka-1.service; enabled; vendor preset: disabled)
   Active: active (running) since 三 2025-08-13 11:49:54 CST; 5s ago
 Main PID: 12287 (java)
   CGroup: /system.slice/kafka-1.service
           └─12287 /usr/local/jdk17/bin/java -Xmx1G -Xms1G -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.aw...

8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12287]: [2025-08-13 11:49:59,407] INFO Client environment:os.memory.max=1024MB (org.apache.zookeeper.ZooKeeper)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12287]: [2025-08-13 11:49:59,407] INFO Client environment:os.memory.total=1024MB (org.apache.zookeeper.ZooKeeper)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12287]: [2025-08-13 11:49:59,410] INFO Initiating client connection, connectString=localhost:2181 sessionTimeout=18000 watcher=kafka.z....ZooKeeper)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12287]: [2025-08-13 11:49:59,419] INFO jute.maxbuffer value is 4194304 Bytes (org.apache.zookeeper.ClientCnxnSocket)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12287]: [2025-08-13 11:49:59,426] INFO zookeeper.request.timeout value is 0. feature enabled=false (org.apache.zookeeper.ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12287]: [2025-08-13 11:49:59,456] INFO Opening socket connection to server localhost/[0:0:0:0:0:0:0:1]:2181. (org.apache.zookeeper.ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12287]: [2025-08-13 11:49:59,462] INFO Socket connection established, initiating session, client: /[0:0:0:0:0:0:0:1]:41508, server: lo...ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12287]: [2025-08-13 11:49:59,467] INFO [ZooKeeperClient Kafka server] Waiting until connected. (kafka.zookeeper.ZooKeeperClient)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12287]: [2025-08-13 11:49:59,560] INFO Session establishment complete on server localhost/[0:0:0:0:0:0:0:1]:2181, session id = 0x10000...ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12287]: [2025-08-13 11:49:59,566] INFO [ZooKeeperClient Kafka server] Connected. (kafka.zookeeper.ZooKeeperClient)

● kafka-2.service - Kafka Broker 2
   Loaded: loaded (/etc/systemd/system/kafka-2.service; enabled; vendor preset: disabled)
   Active: active (running) since 三 2025-08-13 11:49:54 CST; 5s ago
 Main PID: 12288 (java)
   CGroup: /system.slice/kafka-2.service
           └─12288 /usr/local/jdk17/bin/java -Xmx1G -Xms1G -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.aw...

8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12288]: [2025-08-13 11:49:59,370] INFO Client environment:os.memory.max=1024MB (org.apache.zookeeper.ZooKeeper)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12288]: [2025-08-13 11:49:59,370] INFO Client environment:os.memory.total=1024MB (org.apache.zookeeper.ZooKeeper)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12288]: [2025-08-13 11:49:59,374] INFO Initiating client connection, connectString=localhost:2181 sessionTimeout=18000 watcher=kafka.z....ZooKeeper)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12288]: [2025-08-13 11:49:59,401] INFO jute.maxbuffer value is 4194304 Bytes (org.apache.zookeeper.ClientCnxnSocket)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12288]: [2025-08-13 11:49:59,414] INFO zookeeper.request.timeout value is 0. feature enabled=false (org.apache.zookeeper.ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12288]: [2025-08-13 11:49:59,430] INFO Opening socket connection to server localhost/[0:0:0:0:0:0:0:1]:2181. (org.apache.zookeeper.ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12288]: [2025-08-13 11:49:59,436] INFO Socket connection established, initiating session, client: /[0:0:0:0:0:0:0:1]:41506, server: lo...ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12288]: [2025-08-13 11:49:59,441] INFO [ZooKeeperClient Kafka server] Waiting until connected. (kafka.zookeeper.ZooKeeperClient)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12288]: [2025-08-13 11:49:59,525] INFO Session establishment complete on server localhost/[0:0:0:0:0:0:0:1]:2181, session id = 0x10000...ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12288]: [2025-08-13 11:49:59,530] INFO [ZooKeeperClient Kafka server] Connected. (kafka.zookeeper.ZooKeeperClient)

● kafka-3.service - Kafka Broker 3
   Loaded: loaded (/etc/systemd/system/kafka-3.service; enabled; vendor preset: disabled)
   Active: active (running) since 三 2025-08-13 11:49:54 CST; 5s ago
 Main PID: 12289 (java)
   CGroup: /system.slice/kafka-3.service
           └─12289 /usr/local/jdk17/bin/java -Xmx1G -Xms1G -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.aw...

8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12289]: [2025-08-13 11:49:59,456] INFO Client environment:os.memory.max=1024MB (org.apache.zookeeper.ZooKeeper)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12289]: [2025-08-13 11:49:59,456] INFO Client environment:os.memory.total=1024MB (org.apache.zookeeper.ZooKeeper)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12289]: [2025-08-13 11:49:59,459] INFO Initiating client connection, connectString=localhost:2181 sessionTimeout=18000 watcher=kafka.z....ZooKeeper)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12289]: [2025-08-13 11:49:59,487] INFO jute.maxbuffer value is 4194304 Bytes (org.apache.zookeeper.ClientCnxnSocket)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12289]: [2025-08-13 11:49:59,494] INFO zookeeper.request.timeout value is 0. feature enabled=false (org.apache.zookeeper.ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12289]: [2025-08-13 11:49:59,500] INFO [ZooKeeperClient Kafka server] Waiting until connected. (kafka.zookeeper.ZooKeeperClient)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12289]: [2025-08-13 11:49:59,513] INFO Opening socket connection to server localhost/[0:0:0:0:0:0:0:1]:2181. (org.apache.zookeeper.ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12289]: [2025-08-13 11:49:59,538] INFO Socket connection established, initiating session, client: /[0:0:0:0:0:0:0:1]:41510, server: lo...ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12289]: [2025-08-13 11:49:59,558] INFO Session establishment complete on server localhost/[0:0:0:0:0:0:0:1]:2181, session id = 0x10000...ClientCnxn)
8月 13 11:49:59 localhost.localdomain kafka-server-start.sh[12289]: [2025-08-13 11:49:59,564] INFO [ZooKeeperClient Kafka server] Connected. (kafka.zookeeper.ZooKeeperClient)
Hint: Some lines were ellipsized, use -l to show in full.
[root@localhost ~]# jps | egrep 'QuorumPeerMain|Kafka'
12288 Kafka
12289 Kafka
12286 QuorumPeerMain
12287 Kafka

⑪ 重启整机测试(可选)
bash 复制代码
sudo reboot
# 重新登录
jps | egrep 'QuorumPeerMain|Kafka'

再次看到 1 个 QuorumPeerMain + 3 个 Kafka开机自启完成


一句话总结

复制上面 1~6 步即可在 /opt/kafka3.3.2 跑起单机 3 broker 3 副本环境,验证完功能后再考虑真正多机高可用。