08-27-周三_17-09-29
This commit is contained in:
173
数据库/Redis_2025/cluster_scale_in.sh
Normal file
173
数据库/Redis_2025/cluster_scale_in.sh
Normal file
@@ -0,0 +1,173 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "=== Redis 集群缩容操作 ==="
|
||||
|
||||
# 配置参数
|
||||
EXISTING_NODE="127.0.0.1:7001"
|
||||
REMOVE_MASTER="127.0.0.1:7007"
|
||||
REMOVE_SLAVE="127.0.0.1:7008"
|
||||
|
||||
# 1. 检查要删除的节点
|
||||
echo "1. 检查要删除的节点..."
|
||||
|
||||
# 获取要删除的主节点ID
|
||||
REMOVE_MASTER_ID=$(redis-cli -h ${REMOVE_MASTER%:*} -p ${REMOVE_MASTER#*:} CLUSTER MYID 2>/dev/null)
|
||||
REMOVE_SLAVE_ID=$(redis-cli -h ${REMOVE_SLAVE%:*} -p ${REMOVE_SLAVE#*:} CLUSTER MYID 2>/dev/null)
|
||||
|
||||
echo "要删除的主节点: $REMOVE_MASTER (ID: $REMOVE_MASTER_ID)"
|
||||
echo "要删除的从节点: $REMOVE_SLAVE (ID: $REMOVE_SLAVE_ID)"
|
||||
|
||||
# 检查节点状态
|
||||
if [ -z "$REMOVE_MASTER_ID" ]; then
|
||||
echo "❌ 无法连接到要删除的主节点"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. 迁移槽位
|
||||
echo "2. 迁移槽位..."
|
||||
|
||||
# 获取要删除节点的槽位
|
||||
slots_info=$(redis-cli -h ${REMOVE_MASTER%:*} -p ${REMOVE_MASTER#*:} CLUSTER NODES | grep $REMOVE_MASTER_ID)
|
||||
slots_range=$(echo "$slots_info" | awk '{for(i=9;i<=NF;i++) printf "%s%s", $i, (i==NF?"":" ")}')
|
||||
|
||||
echo "要迁移的槽位: $slots_range"
|
||||
|
||||
if [ -n "$slots_range" ] && [ "$slots_range" != "-" ]; then
|
||||
# 解析多个槽位范围(用空格分隔)
|
||||
# 例如: 179-1364 5461-6826 10923-12287
|
||||
slot_ranges_array=()
|
||||
total_slot_count=0
|
||||
|
||||
# 将槽位范围字符串分割成数组
|
||||
IFS=' ' read -ra SLOT_RANGES <<< "$slots_range"
|
||||
|
||||
echo "解析到的槽位范围:"
|
||||
for range in "${SLOT_RANGES[@]}"; do
|
||||
if [[ $range =~ ^([0-9]+)-([0-9]+)$ ]]; then
|
||||
start_slot=${BASH_REMATCH[1]}
|
||||
end_slot=${BASH_REMATCH[2]}
|
||||
range_count=$((end_slot - start_slot + 1))
|
||||
slot_ranges_array+=("$start_slot:$end_slot:$range_count")
|
||||
total_slot_count=$((total_slot_count + range_count))
|
||||
echo " 范围 $start_slot-$end_slot: $range_count 个槽位"
|
||||
elif [[ $range =~ ^[0-9]+$ ]]; then
|
||||
# 单个槽位
|
||||
slot_ranges_array+=("$range:$range:1")
|
||||
total_slot_count=$((total_slot_count + 1))
|
||||
echo " 单个槽位 $range: 1 个槽位"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "总共需要迁移 $total_slot_count 个槽位"
|
||||
|
||||
# 获取目标节点(选择第一个其他主节点)
|
||||
target_nodes=$(redis-cli -h ${EXISTING_NODE%:*} -p ${EXISTING_NODE#*:} CLUSTER NODES | \
|
||||
grep "master" | grep -v $REMOVE_MASTER_ID | head -3)
|
||||
|
||||
echo "目标节点:"
|
||||
echo "$target_nodes"
|
||||
|
||||
# 将目标节点信息存储到数组中
|
||||
target_nodes_array=()
|
||||
while IFS= read -r target_line; do
|
||||
if [ -n "$target_line" ]; then
|
||||
target_nodes_array+=("$target_line")
|
||||
fi
|
||||
done <<< "$target_nodes"
|
||||
|
||||
target_count=${#target_nodes_array[@]}
|
||||
echo "找到 $target_count 个目标节点"
|
||||
|
||||
# 执行槽位迁移 - 处理每个槽位范围
|
||||
echo "开始槽位迁移..."
|
||||
|
||||
range_index=0
|
||||
target_index=0
|
||||
|
||||
# 遍历每个槽位范围
|
||||
for slot_range_info in "${slot_ranges_array[@]}"; do
|
||||
# 解析槽位范围信息 (格式: start:end:count)
|
||||
IFS=':' read -ra RANGE_INFO <<< "$slot_range_info"
|
||||
range_start=${RANGE_INFO[0]}
|
||||
range_end=${RANGE_INFO[1]}
|
||||
range_count=${RANGE_INFO[2]}
|
||||
|
||||
# 选择目标节点(轮询分配)
|
||||
target_line="${target_nodes_array[$target_index]}"
|
||||
target_id=$(echo $target_line | awk '{print $1}')
|
||||
target_addr=$(echo $target_line | awk '{print $2}')
|
||||
|
||||
echo "迁移槽位范围 $range_start-$range_end ($range_count 个槽位) 到 $target_addr"
|
||||
|
||||
# 使用 redis-cli 迁移整个槽位范围
|
||||
redis-cli --cluster reshard ${EXISTING_NODE} \
|
||||
--cluster-from $REMOVE_MASTER_ID \
|
||||
--cluster-to $target_id \
|
||||
--cluster-slots $range_count \
|
||||
--cluster-yes > /dev/null 2>&1
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ 槽位范围 $range_start-$range_end 迁移成功"
|
||||
else
|
||||
echo "❌ 槽位范围 $range_start-$range_end 迁移失败"
|
||||
fi
|
||||
|
||||
# 验证槽位迁移结果
|
||||
echo "验证槽位范围 $range_start-$range_end 的迁移状态..."
|
||||
sleep 5
|
||||
|
||||
# 检查槽位是否已成功迁移
|
||||
migrated_slots=$(redis-cli -h ${EXISTING_NODE%:*} -p ${EXISTING_NODE#*:} CLUSTER NODES | \
|
||||
grep $target_id | awk '{print $9}')
|
||||
echo "目标节点 $target_addr 当前槽位: $migrated_slots"
|
||||
|
||||
# 轮询到下一个目标节点
|
||||
target_index=$(((target_index + 1) % target_count))
|
||||
range_index=$((range_index + 1))
|
||||
done
|
||||
echo "所有槽位范围迁移操作完成"
|
||||
|
||||
else
|
||||
echo "该节点没有分配槽位,跳过迁移"
|
||||
fi
|
||||
|
||||
# 3. 删除从节点
|
||||
echo "3. 删除从节点..."
|
||||
|
||||
echo "删除从节点 $REMOVE_SLAVE..."
|
||||
redis-cli --cluster del-node ${EXISTING_NODE} $REMOVE_SLAVE_ID
|
||||
|
||||
# 4. 删除主节点
|
||||
echo "4. 删除主节点..."
|
||||
|
||||
echo "删除主节点 $REMOVE_MASTER..."
|
||||
redis-cli --cluster del-node ${EXISTING_NODE} $REMOVE_MASTER_ID
|
||||
|
||||
|
||||
# 5. 停止已删除的节点
|
||||
echo "5. 停止已删除的节点..."
|
||||
|
||||
for port in ${REMOVE_MASTER#*:} ${REMOVE_SLAVE#*:}; do
|
||||
echo "停止节点 $port..."
|
||||
redis-cli -p $port SHUTDOWN NOSAVE 2>/dev/null || echo "节点 $port 已停止或不可用"
|
||||
done
|
||||
|
||||
# 6. 验证缩容结果
|
||||
echo "6. 验证缩容结果..."
|
||||
|
||||
echo "剩余集群节点:"
|
||||
redis-cli -h ${EXISTING_NODE%:*} -p ${EXISTING_NODE#*:} CLUSTER NODES
|
||||
|
||||
echo
|
||||
echo "集群状态信息:"
|
||||
redis-cli -h ${EXISTING_NODE%:*} -p ${EXISTING_NODE#*:} CLUSTER INFO
|
||||
|
||||
echo
|
||||
echo "槽位分配验证:"
|
||||
redis-cli -h ${EXISTING_NODE%:*} -p ${EXISTING_NODE#*:} CLUSTER SLOTS
|
||||
|
||||
echo
|
||||
echo "=== 集群缩容完成 ==="
|
||||
echo "已删除主节点: $REMOVE_MASTER"
|
||||
echo "已删除从节点: $REMOVE_SLAVE"
|
||||
echo "集群现有节点数: 6 (3主3从)"
|
Reference in New Issue
Block a user