KAFKA自动修改所有以**开头的主题脚本

目录

我是 自动修改所有 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.创建检查脚本

vi kafka-check-topics.sh

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
相关推荐
Hello.Reader3 小时前
用 Kafka 打通实时数据总线Flink CDC Pipeline 的 Kafka Sink 实战
flink·kafka·linq
周杰伦_Jay5 小时前
【日志处理方案大比拼】 Filebeat+Kafka+Flink+Spark+ES+HDFS VS ELK/AOP/RocketMQ/大厂方案
flink·spark·kafka
回家路上绕了弯5 小时前
高并发订单去重:布隆过滤器过滤已存在订单号的实战方案
分布式·后端
Slow菜鸟6 小时前
Java后端常用技术选型 |(三)分布式篇
java·分布式
q***65697 小时前
Spring Boot集成Kafka:最佳实践与详细指南
spring boot·kafka·linq
大飞哥~BigFei9 小时前
RabbitMq消费延迟衰减重试实现思路
java·分布式·rabbitmq
小泊客20 小时前
使用讯飞星火 Spark X1-32K 打造本地知识助手
大数据·分布式·spark·大模型应用·本地知识助手
百***79461 天前
Spring集成kafka的最佳方式
spring·kafka·linq
Ace_31750887761 天前
京东关键字搜索接口逆向:从动态签名破解到分布式请求调度
分布式·python