3.3.2 为什么更合适

3.3.2 是 3.3 线的最后一个补丁版,修掉 20 个 bug(含潜在数据丢失/稳定性问题)。

Scala 2.13 比 2.12 体积小一点点,官方也写 “建议使用 2.13”。

以后真要扩容到多机,同一版本直接复制配置即可,避免混版本。

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

用同一台机器开 3 个 Kafka 进程,每个进程一个 broker.id 和独立端口/目录,Zookeeper 仍用同一实例。

只能验证功能/调试用,真正高可用必须 ≥3 台物理机。

三、10 分钟落地步骤

前置依赖

sudo yum install -y java-11-openjdk-devel wget

java -version # 确认 11+

目录规划

sudo mkdir -p /opt/kafka-cluster

cd /opt/kafka-cluster

下载并解压 3.3.2

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

起 Zookeeper(单节点)

# 用自带脚本即可

nohup kafka/bin/zookeeper-server-start.sh kafka/config/zookeeper.properties > zk.log 2>&1 &

为 3 个 broker 准备配置文件

把下面三段分别写进 kafka-1/config/server.properties、kafka-2/config/server.properties、kafka-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

其余保持默认即可。

启动 3 个 broker

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 &

验证 3 副本 topic

# 建 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。

简单生产/消费测试

# 生产

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

一、提前确认

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]#

二、解压并更名

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

三、建数据 / 日志目录

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 单节点配置

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 配置

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 个关键配置一次性写入对应文件:

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

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

# 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=value 或 key = value

4 只处理 #advertised.listeners 的注释行 改成 #? 同时匹配已取消注释或仍注释的行

5 无 -r 扩展正则 加 -r(GNU sed) 让 ?、`

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

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

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

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

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

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

② 赋可执行权限

chmod +x ~/start-kafka.sh

③ 运行脚本

~/start-kafka.sh

#运行结果

Zookeeper + 3 brokers started. Logs under /opt/kafka3.3.2/#

④ 验证是否都起来了

jps | egrep 'QuorumPeerMain|Kafka'

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

#运行结果(有偏差)

27940 Kafka

26891 QuorumPeerMain

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

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

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

立即查日志定位原因 ,然后这里我的是空目录

# 看看每个 broker 日志末尾 20 行

tail -n 20 /opt/kafka3.3.2/broker-*.log

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

一键补齐缺失目录 & 权限

mkdir -p /opt/kafka3.3.2/data/{kafka-logs-1,kafka-logs-2,kafka-logs-3}

chown -R $(whoami):$(whoami) /opt/kafka3.3.2

先停后启(干净重启)

# 如果还有残存进程

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、修复步骤(复制即用)

杀干净所有残留进程

pkill -9 -f 'kafka\.Kafka'

pkill -f QuorumPeerMain

一次性建目录 + 删 .lock

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

把 3 份配置端口全部改成 9191/9192/9193

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

启动并验证

~/start-kafka.sh

sleep 5 && jps | egrep 'QuorumPeerMain|Kafka'

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

[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 ==

确认 9092 已释放

ss -lntup | grep :9092 # 应无结果

3、后续不再踩坑的 3 条建议

永远先杀干净旧进程再启动新配置。

端口批量错开(如 9191/9192/9193),避免手动改漏。

日志为空或报错时立即 tail -n 30,定位关键字只用 10 秒。

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

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

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

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

? 验证

# 建 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,3 且 Isr: 1,2,3 即成功。

八、开机自启(可选)

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

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

① 创建 systemd 服务文件

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 脚本(如果还没有)

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

③ 重载并设为开机自启

sudo systemctl daemon-reload

sudo systemctl enable --now kafka

④ 验证

#一般检查到这一步就可以,出现active就成功,不用之后的重启

systemctl status kafka

⑤慎重验证

# 重启后自动拉起,该命令用于重启整个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

[root@localhost ~]# jps | egrep 'QuorumPeerMain|Kafka'

27940 Kafka

26891 QuorumPeerMain

② 立即查看 3 份日志尾

[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,现场报错

# 先停干净

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 被谁占用

[root@localhost ~]# ss -lntup|grep 9092

tcp LISTEN 0 50 [::]:9092 [::]:* users:(("java",pid=27940,fd=125))

⑤杀掉旧进程 & 清理锁文件

# 杀掉所有残留

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

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 单元

# 查出 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

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

for i in 1 2 3; do

port=$((9190+i))

sudo tee /etc/systemd/system/kafka-${i}.service >/dev/null <

[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

⑨ 重载 & 自启

sudo systemctl daemon-reload

sudo systemctl enable --now zookeeper

for i in 1 2 3; do

sudo systemctl enable --now kafka-${i}

done

⑩ 最终验证

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐