目录
- [在任意一个 Kafka 节点执行](#在任意一个 Kafka 节点执行)
-
-
- 1.创建脚本目录
- 2.创建主脚本(修改副本配置)
- 3.粘贴脚本内容
- 4.创建检查脚本
- 5.粘贴脚本内容
- 6.添加执行权限
- 7.先检查当前状态
- 8.执行副本修改
- 9.注意事项
- 10.监控集群状态
- 11.可以暂停重分配(如果影响业务)
- 12.验证完成后
- [13.查看某个 topic 的详细信息](#13.查看某个 topic 的详细信息)
- 13.重启消费者(可选但建议)
-
我是 自动修改所有 sdyt 开头的 topic 配置,将副本因子改为 3
在任意一个 Kafka 节点执行
1.创建脚本目录
java
mkdir -p /opt/kafka/scripts
cd /opt/kafka/scripts
2.创建主脚本(修改副本配置)
vi kafka-update-sdyt-topics.sh
3.粘贴脚本内容
java
#!/bin/bash
# Kafka 批量修改 sdyt 开头的 topic 副本因子脚本
# 将副本因子从 1 改为 3
set -e
# 配置参数
BOOTSTRAP_SERVER="172.16.55.72:9092,172.16.55.73:9092,172.16.55.74:9092"
KAFKA_HOME="/opt/kafka/kafka_2.13-3.7.1"
TEMP_DIR="/tmp/kafka_reassignment"
LOG_FILE="/tmp/kafka_reassignment.log"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 创建临时目录
mkdir -p "$TEMP_DIR"
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}Kafka Topic 副本配置修改脚本${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo "Bootstrap Server: $BOOTSTRAP_SERVER"
echo "临时目录: $TEMP_DIR"
echo "日志文件: $LOG_FILE"
echo ""
# 记录日志
log() {
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
log "========== 开始执行 =========="
# 1. 获取所有 sdyt 开头的 topic
echo -e "${YELLOW}[1/5] 正在获取所有 sdyt 开头的 topic...${NC}"
TOPICS=$($KAFKA_HOME/bin/kafka-topics.sh \
--bootstrap-server "$BOOTSTRAP_SERVER" \
--list | grep "^sdyt")
if [ -z "$TOPICS" ]; then
echo -e "${RED}错误:没有找到 sdyt 开头的 topic${NC}"
log "错误:没有找到 sdyt 开头的 topic"
exit 1
fi
echo -e "${GREEN}找到以下 topic:${NC}"
echo "$TOPICS"
log "找到 topic 列表:$TOPICS"
echo ""
# 统计 topic 数量
TOPIC_COUNT=$(echo "$TOPICS" | wc -l)
echo -e "${GREEN}共找到 $TOPIC_COUNT 个 topic${NC}"
echo ""
# 确认是否继续
read -p "是否继续修改这些 topic 的副本配置?(y/n): " CONFIRM
if [ "$CONFIRM" != "y" ]; then
echo -e "${YELLOW}操作已取消${NC}"
exit 0
fi
# 2. 为每个 topic 生成副本分配方案
echo ""
echo -e "${YELLOW}[2/5] 正在生成副本分配方案...${NC}"
for TOPIC in $TOPICS; do
log "处理 topic: $TOPIC"
echo -e "${GREEN}处理 topic: $TOPIC${NC}"
# 获取 topic 详细信息
TOPIC_INFO=$($KAFKA_HOME/bin/kafka-topics.sh \
--bootstrap-server "$BOOTSTRAP_SERVER" \
--describe --topic "$TOPIC")
echo "$TOPIC_INFO"
log "$TOPIC_INFO"
# 获取分区数量
PARTITION_COUNT=$(echo "$TOPIC_INFO" | grep "PartitionCount" | awk '{print $4}')
echo " 分区数: $PARTITION_COUNT"
log " 分区数: $PARTITION_COUNT"
# 生成 JSON 文件
JSON_FILE="$TEMP_DIR/reassignment-${TOPIC}.json"
echo "{" > "$JSON_FILE"
echo ' "version": 1,' >> "$JSON_FILE"
echo ' "partitions": [' >> "$JSON_FILE"
# 为每个分区生成副本分配
for ((i=0; i<$PARTITION_COUNT; i++)); do
# 计算副本分布(轮询方式)
BROKER1=$((i % 3))
BROKER2=$(((i + 1) % 3))
BROKER3=$(((i + 2) % 3))
if [ $i -eq $((PARTITION_COUNT - 1)) ]; then
# 最后一个分区,不加逗号
echo " {\"topic\": \"$TOPIC\", \"partition\": $i, \"replicas\": [$BROKER1,$BROKER2,$BROKER3]}" >> "$JSON_FILE"
else
echo " {\"topic\": \"$TOPIC\", \"partition\": $i, \"replicas\": [$BROKER1,$BROKER2,$BROKER3]}," >> "$JSON_FILE"
fi
done
echo ' ]' >> "$JSON_FILE"
echo '}' >> "$JSON_FILE"
echo " 生成配置文件: $JSON_FILE"
log " 生成配置文件: $JSON_FILE"
echo ""
done
# 3. 执行副本重分配
echo ""
echo -e "${YELLOW}[3/5] 正在执行副本重分配...${NC}"
echo -e "${RED}警告:此操作会占用大量网络和磁盘 I/O,请确认在低峰期执行!${NC}"
read -p "确认执行重分配?(yes/no): " CONFIRM_EXEC
if [ "$CONFIRM_EXEC" != "yes" ]; then
echo -e "${YELLOW}操作已取消${NC}"
echo -e "${GREEN}配置文件已生成在: $TEMP_DIR${NC}"
exit 0
fi
for TOPIC in $TOPICS; do
JSON_FILE="$TEMP_DIR/reassignment-${TOPIC}.json"
echo ""
echo -e "${GREEN}执行 topic: $TOPIC${NC}"
log "执行重分配: $TOPIC"
$KAFKA_HOME/bin/kafka-reassign-partitions.sh \
--bootstrap-server "$BOOTSTRAP_SERVER" \
--reassignment-json-file "$JSON_FILE" \
--execute 2>&1 | tee -a "$LOG_FILE"
if [ ${PIPESTATUS[0]} -eq 0 ]; then
echo -e "${GREEN} ✓ 提交成功${NC}"
log " ✓ $TOPIC 提交成功"
else
echo -e "${RED} ✗ 提交失败${NC}"
log " ✗ $TOPIC 提交失败"
fi
done
# 4. 监控重分配进度
echo ""
echo -e "${YELLOW}[4/5] 正在监控重分配进度...${NC}"
echo -e "${YELLOW}提示:副本重分配是一个耗时的过程,请耐心等待${NC}"
echo ""
ALL_COMPLETED=false
CHECK_INTERVAL=30
while [ "$ALL_COMPLETED" = false ]; do
ALL_COMPLETED=true
for TOPIC in $TOPICS; do
JSON_FILE="$TEMP_DIR/reassignment-${TOPIC}.json"
VERIFY_OUTPUT=$($KAFKA_HOME/bin/kafka-reassign-partitions.sh \
--bootstrap-server "$BOOTSTRAP_SERVER" \
--reassignment-json-file "$JSON_FILE" \
--verify 2>&1)
if echo "$VERIFY_OUTPUT" | grep -q "in progress"; then
ALL_COMPLETED=false
echo -e "${YELLOW}$(date +'%H:%M:%S') - Topic $TOPIC: 重分配进行中...${NC}"
log "$(date +'%H:%M:%S') - Topic $TOPIC: 重分配进行中"
elif echo "$VERIFY_OUTPUT" | grep -q "successfully completed"; then
echo -e "${GREEN}$(date +'%H:%M:%S') - Topic $TOPIC: ✓ 完成${NC}"
log "$(date +'%H:%M:%S') - Topic $TOPIC: 完成"
else
echo -e "${RED}$(date +'%H:%M:%S') - Topic $TOPIC: 状态未知${NC}"
echo "$VERIFY_OUTPUT"
log "$(date +'%H:%M:%S') - Topic $TOPIC: $VERIFY_OUTPUT"
fi
done
if [ "$ALL_COMPLETED" = false ]; then
echo ""
echo "等待 $CHECK_INTERVAL 秒后再次检查..."
sleep $CHECK_INTERVAL
echo ""
fi
done
# 5. 验证最终结果
echo ""
echo -e "${YELLOW}[5/5] 正在验证最终配置...${NC}"
echo ""
for TOPIC in $TOPICS; do
echo -e "${GREEN}Topic: $TOPIC${NC}"
$KAFKA_HOME/bin/kafka-topics.sh \
--bootstrap-server "$BOOTSTRAP_SERVER" \
--describe --topic "$TOPIC" | grep -E "Topic:|Partition:" | tee -a "$LOG_FILE"
echo ""
done
# 完成
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}✓ 所有 topic 副本配置修改完成!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo "详细日志: $LOG_FILE"
echo "配置文件目录: $TEMP_DIR"
echo ""
log "========== 执行完成 =========="
# 清理选项
read -p "是否删除临时文件?(y/n): " CLEANUP
if [ "$CLEANUP" = "y" ]; then
rm -rf "$TEMP_DIR"
echo -e "${GREEN}临时文件已清理${NC}"
log "临时文件已清理"
else
echo -e "${YELLOW}临时文件保留在: $TEMP_DIR${NC}"
fi
echo ""
echo -e "${GREEN}建议:重启所有消费者以刷新元数据${NC}"
4.创建检查脚本
5.粘贴脚本内容
java
#!/bin/bash
# Kafka Topic 副本状态检查脚本
BOOTSTRAP_SERVER="172.16.55.72:9092,172.16.55.73:9092,172.16.55.74:9092"
KAFKA_HOME="/opt/kafka/kafka_2.13-3.7.1"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Kafka Topic 副本状态检查${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
# 获取所有 sdyt 开头的 topic
TOPICS=$($KAFKA_HOME/bin/kafka-topics.sh \
--bootstrap-server "$BOOTSTRAP_SERVER" \
--list | grep "^sdyt")
if [ -z "$TOPICS" ]; then
echo -e "${RED}错误:没有找到 sdyt 开头的 topic${NC}"
exit 1
fi
echo -e "${GREEN}找到 $(echo "$TOPICS" | wc -l) 个 sdyt 开头的 topic${NC}"
echo ""
# 统计变量
TOTAL_TOPICS=0
RF1_TOPICS=0
RF3_TOPICS=0
UNDER_REPLICATED=0
# 表格头
printf "${BLUE}%-50s %-12s %-12s %-20s${NC}\n" "Topic Name" "Partitions" "Repl.Factor" "Status"
echo "---------------------------------------------------------------------------------------------------"
# 检查每个 topic
for TOPIC in $TOPICS; do
TOTAL_TOPICS=$((TOTAL_TOPICS + 1))
# 获取 topic 信息
TOPIC_INFO=$($KAFKA_HOME/bin/kafka-topics.sh \
--bootstrap-server "$BOOTSTRAP_SERVER" \
--describe --topic "$TOPIC" 2>/dev/null)
# 提取分区数和副本因子
PARTITION_COUNT=$(echo "$TOPIC_INFO" | grep "PartitionCount" | awk '{print $4}')
REPLICATION_FACTOR=$(echo "$TOPIC_INFO" | grep "ReplicationFactor" | awk '{print $6}')
# 检查是否有副本不同步
UNDER_REPLICATED_PARTITIONS=$(echo "$TOPIC_INFO" | grep "Isr:" | awk '{if(NF<6) print}' | wc -l)
# 状态判断
if [ "$REPLICATION_FACTOR" = "1" ]; then
STATUS="${RED}⚠ RF=1 (无副本)${NC}"
RF1_TOPICS=$((RF1_TOPICS + 1))
elif [ "$REPLICATION_FACTOR" = "3" ]; then
if [ "$UNDER_REPLICATED_PARTITIONS" -gt 0 ]; then
STATUS="${YELLOW}⚠ RF=3 (有分区未同步)${NC}"
UNDER_REPLICATED=$((UNDER_REPLICATED + 1))
else
STATUS="${GREEN}✓ RF=3 (正常)${NC}"
fi
RF3_TOPICS=$((RF3_TOPICS + 1))
else
STATUS="${YELLOW}⚠ RF=$REPLICATION_FACTOR${NC}"
fi
printf "%-50s %-12s %-12s %-20s\n" "$TOPIC" "$PARTITION_COUNT" "$REPLICATION_FACTOR" "$(echo -e $STATUS)"
done
# 统计摘要
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}统计摘要${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
echo "总 Topic 数: $TOTAL_TOPICS"
echo -e "${RED}副本因子 = 1: $RF1_TOPICS (需要修改)${NC}"
echo -e "${GREEN}副本因子 = 3: $RF3_TOPICS${NC}"
if [ "$UNDER_REPLICATED" -gt 0 ]; then
echo -e "${YELLOW}有未同步分区的 Topic: $UNDER_REPLICATED${NC}"
fi
echo ""
# 建议
if [ "$RF1_TOPICS" -gt 0 ]; then
echo -e "${YELLOW}========================================${NC}"
echo -e "${YELLOW}⚠ 建议${NC}"
echo -e "${YELLOW}========================================${NC}"
echo -e "${YELLOW}发现 $RF1_TOPICS 个 topic 的副本因子为 1${NC}"
echo -e "${YELLOW}建议运行副本修改脚本将其改为 3${NC}"
echo ""
echo -e "${GREEN}执行命令:${NC}"
echo " bash kafka-topic-replication-script.sh"
echo ""
fi
# 详细检查选项
echo ""
read -p "是否查看详细的副本分布信息?(y/n): " DETAIL
if [ "$DETAIL" = "y" ]; then
echo ""
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}详细副本分布${NC}"
echo -e "${BLUE}========================================${NC}"
for TOPIC in $TOPICS; do
echo ""
echo -e "${GREEN}Topic: $TOPIC${NC}"
$KAFKA_HOME/bin/kafka-topics.sh \
--bootstrap-server "$BOOTSTRAP_SERVER" \
--describe --topic "$TOPIC" | grep "Partition:"
done
fi
echo ""
6.添加执行权限
java
chmod +x kafka-update-sdyt-topics.sh
chmod +x kafka-check-topics.sh
7.先检查当前状态
java
bashcd /opt/kafka/scripts
./kafka-check-topics.sh
这会显示:
所有 sdyt 开头的 topic
当前的分区数和副本因子
哪些 topic 需要修改
8.执行副本修改
java
bashcd /opt/kafka/scripts
./kafka-update-sdyt-topics.sh
脚本会:
✅ 自动找出所有 sdyt 开头的 topic
✅ 显示列表让你确认
✅ 生成副本分配方案(3 副本,均匀分布)
✅ 执行重分配
✅ 实时监控进度
✅ 验证最终结果
9.注意事项
⚠️ 重要提示:
在低峰期执行
副本重分配会占用大量网络和磁盘 I/O
建议在业务低峰期(如凌晨)执行
执行时间估算
取决于数据量大小
1GB 数据约需 1-5 分钟
大 topic 可能需要数小时
10.监控集群状态
powershell
bash # 在另一个终端监控
watch -n 5 "kafka-topics.sh --bootstrap-server 172.16.55.72:9092 \
--describe --under-replicated-partitions"
11.可以暂停重分配(如果影响业务)
powershell
bash # 创建空的 JSON 文件
echo '{"version":1,"partitions":[]}' > /tmp/cancel.json
# 执行取消
kafka-reassign-partitions.sh \
--bootstrap-server 172.16.55.72:9092 \
--reassignment-json-file /tmp/cancel.json \
--execute
12.验证完成后
powershell
bash# 再次检查状态
./kafka-check-topics.sh
13.查看某个 topic 的详细信息
java
kafka-topics.sh --bootstrap-server 172.16.55.72:9092 \
--describe --topic sdyt-xxxx
应该看到类似输出:
Topic: sdyt-xxxx Partition: 0 Leader: 0 Replicas: 0,1,2 Isr: 0,1,2
Topic: sdyt-xxxx Partition: 1 Leader: 1 Replicas: 1,2,0 Isr: 1,2,0
Topic: sdyt-xxxx Partition: 2 Leader: 2 Replicas: 2,0,1 Isr: 2,0,1
13.重启消费者(可选但建议)
java
systemctl restart kafka