Redis 主从 + 哨兵 高可用环境搭建脚本(改进版)

#!/bin/bash

# ================================================
# Redis 主从 + 哨兵 高可用环境搭建脚本(改进版)
# ================================================

# --- 1. 定义基础配置 ---
REDIS_BASE_PORT=6379               # Redis Master 起始端口
SENTINEL_BASE_PORT=26379           # Sentinel 起始端口
MASTER_IP="127.0.0.1"              # Redis Master IP(可改为实际服务器IP)
MASTER_NAME="mymaster"             # Redis 主节点名称
QUORUM=2                           # 哨兵判定主节点失效所需的票数
INSTANCE_COUNT=3                   # Redis 实例总数(1 Master + 2 Replicas)
SENTINEL_COUNT=3                   # Sentinel 实例数量
WORK_DIR="redis-ha"                # 所有配置与数据存放的目录
REDIS_PASSWORD="hanserwei"         # Redis 访问密码

# 获取工作目录的绝对路径
ABSOLUTE_WORK_DIR=$(pwd)/$WORK_DIR

echo "=========================================="
echo "Redis 主从 + 哨兵高可用部署脚本"
echo "=========================================="
echo "Master 端口: $REDIS_BASE_PORT"
echo "Replica 数量: $((INSTANCE_COUNT - 1))"
echo "Sentinel 数量: $SENTINEL_COUNT"
echo "工作目录: $ABSOLUTE_WORK_DIR"
echo "=========================================="

# --- 2. 检查 Redis 是否安装 ---
if ! command -v redis-server &> /dev/null; then
    echo "✗ 错误: 未检测到 redis-server,请先安装 Redis"
    exit 1
fi

if ! command -v redis-cli &> /dev/null; then
    echo "✗ 错误: 未检测到 redis-cli,请先安装 Redis"
    exit 1
fi

echo "✓ Redis 已安装"

# --- 3. 清理并创建工作目录 ---
if [ -d "$WORK_DIR" ]; then
    echo ""
    read -p "检测到旧的 $WORK_DIR 目录,是否清理? (y/n): " confirm
    if [ "$confirm" = "y" ]; then
        echo "清理旧的 $WORK_DIR 目录..."
        # 停止所有 Redis 进程
        for port in $(seq $REDIS_BASE_PORT $((REDIS_BASE_PORT + INSTANCE_COUNT - 1))); do
            redis-cli -p $port -a $REDIS_PASSWORD --no-auth-warning shutdown 2>/dev/null
        done
        # 停止所有 Sentinel 进程
        for port in $(seq $SENTINEL_BASE_PORT $((SENTINEL_BASE_PORT + SENTINEL_COUNT - 1))); do
            redis-cli -p $port shutdown 2>/dev/null
        done
        sleep 1
        rm -rf $WORK_DIR
        rm -f stop_redis_ha.sh test_redis_ha.sh
    else
        echo "取消部署"
        exit 0
    fi
fi

mkdir -p $WORK_DIR
echo "✓ 创建工作目录: $ABSOLUTE_WORK_DIR"

# --- 4. 创建 Redis 实例配置文件 ---
echo ""
echo "--- 创建 Redis 实例配置 ---"
for i in $(seq 0 $((INSTANCE_COUNT - 1))); do
    PORT=$((REDIS_BASE_PORT + i))
    CONF_FILE="$WORK_DIR/redis-$PORT.conf"
    DATA_DIR="$ABSOLUTE_WORK_DIR/data-$PORT"

    # 创建数据目录
    mkdir -p "$DATA_DIR"

    if [ $i -eq 0 ]; then
        echo "创建 Master 配置: redis-$PORT.conf"
    else
        echo "创建 Replica 配置: redis-$PORT.conf"
    fi

    cat > "$CONF_FILE" <<-EOF
# 基础配置
port $PORT
daemonize yes
pidfile $ABSOLUTE_WORK_DIR/redis-$PORT.pid
logfile "$ABSOLUTE_WORK_DIR/redis-$PORT.log"
dir $DATA_DIR
bind 0.0.0.0
protected-mode no

# 持久化配置
appendonly yes
appendfilename "appendonly.aof"
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb

# 安全配置
requirepass $REDIS_PASSWORD
masterauth $REDIS_PASSWORD

# 性能优化
maxmemory 256mb
maxmemory-policy allkeys-lru
tcp-backlog 511
timeout 0
tcp-keepalive 300

# 复制配置
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
replica-priority 100
EOF

    # 为从节点添加 replicaof 配置
    if [ $i -ne 0 ]; then
        echo "replicaof $MASTER_IP $REDIS_BASE_PORT" >> "$CONF_FILE"
    fi
done

echo "✓ Redis 配置文件创建完成"

# --- 5. 启动 Redis 实例 ---
echo ""
echo "--- 启动 Redis 实例 ---"
for i in $(seq 0 $((INSTANCE_COUNT - 1))); do
    PORT=$((REDIS_BASE_PORT + i))
    ROLE=$( [ $i -eq 0 ] && echo "Master" || echo "Replica" )
    echo "启动 $ROLE $PORT..."
    redis-server "$WORK_DIR/redis-$PORT.conf"

    if [ $? -eq 0 ]; then
        echo "✓ $ROLE $PORT 启动成功"
    else
        echo "✗ $ROLE $PORT 启动失败"
        exit 1
    fi
done

sleep 2

# --- 6. 验证 Redis 实例状态 ---
echo ""
echo "--- 验证 Redis 实例状态 ---"
all_running=true
for i in $(seq 0 $((INSTANCE_COUNT - 1))); do
    PORT=$((REDIS_BASE_PORT + i))
    ROLE=$( [ $i -eq 0 ] && echo "Master" || echo "Replica" )
    if redis-cli -p $PORT -a $REDIS_PASSWORD --no-auth-warning ping > /dev/null 2>&1; then
        echo "✓ $ROLE $PORT: 运行正常"
    else
        echo "✗ $ROLE $PORT: 运行异常"
        all_running=false
    fi
done

if [ "$all_running" = false ]; then
    echo "部分实例启动失败,请检查日志"
    exit 1
fi

# --- 7. 验证主从复制状态 ---
echo ""
echo "--- 验证主从复制状态 ---"
REPL_INFO=$(redis-cli -p $REDIS_BASE_PORT -a $REDIS_PASSWORD --no-auth-warning INFO replication)
echo "$REPL_INFO" | grep -E "role:|connected_slaves:"

CONNECTED_SLAVES=$(echo "$REPL_INFO" | grep "connected_slaves:" | cut -d: -f2 | tr -d '\r')
if [ "$CONNECTED_SLAVES" -eq $((INSTANCE_COUNT - 1)) ]; then
    echo "✓ 主从复制正常:Master 已连接 $CONNECTED_SLAVES 个 Replica"
else
    echo "⚠ 警告:预期 $((INSTANCE_COUNT - 1)) 个 Replica,实际连接 $CONNECTED_SLAVES 个"
fi

# --- 8. 创建 Sentinel 配置文件 ---
echo ""
echo "--- 创建 Sentinel 配置 ---"
for i in $(seq 0 $((SENTINEL_COUNT - 1))); do
    PORT=$((SENTINEL_BASE_PORT + i))
    CONF_FILE="$WORK_DIR/sentinel-$PORT.conf"

    echo "创建 Sentinel 配置: sentinel-$PORT.conf"
    cat > "$CONF_FILE" <<-EOF
# 基础配置
port $PORT
daemonize yes
pidfile $ABSOLUTE_WORK_DIR/sentinel-$PORT.pid
logfile "$ABSOLUTE_WORK_DIR/sentinel-$PORT.log"
dir $ABSOLUTE_WORK_DIR
bind 0.0.0.0
protected-mode no

# 监控配置
sentinel monitor $MASTER_NAME $MASTER_IP $REDIS_BASE_PORT $QUORUM
sentinel auth-pass $MASTER_NAME $REDIS_PASSWORD

# 故障转移配置
sentinel down-after-milliseconds $MASTER_NAME 5000
sentinel parallel-syncs $MASTER_NAME 1
sentinel failover-timeout $MASTER_NAME 60000

# 通知脚本(可选)
# sentinel notification-script $MASTER_NAME /path/to/notify.sh
# sentinel client-reconfig-script $MASTER_NAME /path/to/reconfig.sh
EOF
done

echo "✓ Sentinel 配置文件创建完成"

# --- 9. 启动 Sentinel 实例 ---
echo ""
echo "--- 启动 Sentinel 实例 ---"
for i in $(seq 0 $((SENTINEL_COUNT - 1))); do
    PORT=$((SENTINEL_BASE_PORT + i))
    echo "启动 Sentinel $PORT..."
    redis-server "$WORK_DIR/sentinel-$PORT.conf" --sentinel

    if [ $? -eq 0 ]; then
        echo "✓ Sentinel $PORT 启动成功"
    else
        echo "✗ Sentinel $PORT 启动失败"
        exit 1
    fi
done

sleep 3

# --- 10. 验证 Sentinel 状态 ---
echo ""
echo "--- 验证 Sentinel 状态 ---"
SENTINEL_INFO=$(redis-cli -p $SENTINEL_BASE_PORT sentinel masters 2>/dev/null)

if [ $? -eq 0 ]; then
    echo "✓ Sentinel 集群运行正常"
    echo ""
    echo "Master 信息:"
    echo "$SENTINEL_INFO" | grep -E "name|ip|port|flags|num-slaves|num-other-sentinels"
else
    echo "✗ Sentinel 状态检查失败"
fi

# --- 11. 输出部署信息 ---
echo ""
echo "=========================================="
echo "✓ Redis 主从+哨兵环境部署完成!"
echo "=========================================="
echo "Redis 实例:"
echo "  Master: 127.0.0.1:$REDIS_BASE_PORT"
for i in $(seq 1 $((INSTANCE_COUNT - 1))); do
    PORT=$((REDIS_BASE_PORT + i))
    echo "  Replica $i: 127.0.0.1:$PORT"
done
echo ""
echo "Sentinel 实例:"
for i in $(seq 0 $((SENTINEL_COUNT - 1))); do
    PORT=$((SENTINEL_BASE_PORT + i))
    echo "  Sentinel $((i+1)): 127.0.0.1:$PORT"
done
echo ""
echo "认证密码: $REDIS_PASSWORD"
echo "Master 名称: $MASTER_NAME"
echo "工作目录: $ABSOLUTE_WORK_DIR"
echo ""
echo "=========================================="
echo "常用操作命令:"
echo "=========================================="
echo "1. 连接到 Master:"
echo "   redis-cli -p $REDIS_BASE_PORT -a $REDIS_PASSWORD"
echo ""
echo "2. 查看主从复制信息:"
echo "   redis-cli -p $REDIS_BASE_PORT -a $REDIS_PASSWORD INFO replication"
echo ""
echo "3. 连接到 Sentinel:"
echo "   redis-cli -p $SENTINEL_BASE_PORT"
echo ""
echo "4. 查看监控的 Master:"
echo "   redis-cli -p $SENTINEL_BASE_PORT SENTINEL masters"
echo ""
echo "5. 获取 Master 地址:"
echo "   redis-cli -p $SENTINEL_BASE_PORT SENTINEL get-master-addr-by-name $MASTER_NAME"
echo ""
echo "6. 查看所有 Sentinel:"
echo "   redis-cli -p $SENTINEL_BASE_PORT SENTINEL sentinels $MASTER_NAME"
echo ""
echo "7. 手动触发故障转移(测试用):"
echo "   redis-cli -p $SENTINEL_BASE_PORT SENTINEL failover $MASTER_NAME"
echo ""
echo "8. 测试高可用:"
echo "   ./test_redis_ha.sh"
echo ""
echo "9. 停止环境:"
echo "   ./stop_redis_ha.sh"
echo "=========================================="

# --- 12. 创建停止脚本 ---
echo ""
echo "创建停止脚本 stop_redis_ha.sh..."
cat > stop_redis_ha.sh <<-'EOF'
#!/bin/bash

REDIS_BASE_PORT=6379
SENTINEL_BASE_PORT=26379
INSTANCE_COUNT=3
SENTINEL_COUNT=3
WORK_DIR="redis-ha"
REDIS_PASSWORD="hanserwei"

echo "=========================================="
echo "停止 Redis 主从+哨兵环境"
echo "=========================================="

# 停止所有 Sentinel
echo ""
echo "停止 Sentinel 实例..."
for port in $(seq $SENTINEL_BASE_PORT $(($SENTINEL_BASE_PORT + $SENTINEL_COUNT - 1))); do
    echo "停止 Sentinel $port..."
    redis-cli -p $port shutdown 2>/dev/null
    if [ $? -eq 0 ]; then
        echo "✓ Sentinel $port 已停止"
    else
        echo "✗ Sentinel $port 停止失败或未运行"
    fi
done

sleep 1

# 停止所有 Redis 实例
echo ""
echo "停止 Redis 实例..."
for port in $(seq $REDIS_BASE_PORT $(($REDIS_BASE_PORT + $INSTANCE_COUNT - 1))); do
    echo "停止 Redis $port..."
    redis-cli -p $port -a $REDIS_PASSWORD --no-auth-warning shutdown 2>/dev/null
    if [ $? -eq 0 ]; then
        echo "✓ Redis $port 已停止"
    else
        echo "✗ Redis $port 停止失败或未运行"
    fi
done

sleep 1

# 询问是否删除数据
echo ""
read -p "是否删除数据目录 $WORK_DIR? (y/n): " confirm
if [ "$confirm" = "y" ]; then
    echo "删除工作目录 $WORK_DIR..."
    rm -rf $WORK_DIR
    rm -f test_redis_ha.sh
    echo "✓ 清理完成"
else
    echo "保留数据目录"
fi

echo ""
echo "=========================================="
echo "环境已停止"
echo "=========================================="
EOF

chmod +x stop_redis_ha.sh
echo "✓ 停止脚本创建完成"

# --- 13. 创建测试脚本 ---
echo ""
echo "创建测试脚本 test_redis_ha.sh..."
cat > test_redis_ha.sh <<-'EOF'
#!/bin/bash

REDIS_BASE_PORT=6379
SENTINEL_BASE_PORT=26379
REDIS_PASSWORD="hanserwei"
MASTER_NAME="mymaster"

echo "=========================================="
echo "测试 Redis 主从+哨兵高可用"
echo "=========================================="

# 1. 获取当前 Master
echo ""
echo "1. 查询当前 Master 地址..."
MASTER_ADDR=$(redis-cli -p $SENTINEL_BASE_PORT SENTINEL get-master-addr-by-name $MASTER_NAME 2>/dev/null)
if [ $? -eq 0 ]; then
    MASTER_IP=$(echo "$MASTER_ADDR" | head -n 1)
    MASTER_PORT=$(echo "$MASTER_ADDR" | tail -n 1)
    echo "✓ 当前 Master: $MASTER_IP:$MASTER_PORT"
else
    echo "✗ 无法获取 Master 地址"
    exit 1
fi

# 2. 写入测试数据
echo ""
echo "2. 写入测试数据到 Master..."
for i in {1..10}; do
    redis-cli -h $MASTER_IP -p $MASTER_PORT -a $REDIS_PASSWORD --no-auth-warning \
        SET "test_key_$i" "value_$i" > /dev/null
    if [ $? -eq 0 ]; then
        echo "✓ 写入 test_key_$i"
    else
        echo "✗ 写入 test_key_$i 失败"
    fi
done

# 3. 从 Replica 读取数据
echo ""
echo "3. 从 Replica 读取数据..."
REPLICA_PORT=$((REDIS_BASE_PORT + 1))
for i in {1..5}; do
    value=$(redis-cli -p $REPLICA_PORT -a $REDIS_PASSWORD --no-auth-warning get "test_key_$i" 2>/dev/null)
    if [ $? -eq 0 ]; then
        echo "✓ test_key_$i = $value"
    else
        echo "✗ 读取 test_key_$i 失败"
    fi
done

# 4. 查看复制延迟
echo ""
echo "4. 查看主从复制延迟..."
MASTER_OFFSET=$(redis-cli -h $MASTER_IP -p $MASTER_PORT -a $REDIS_PASSWORD --no-auth-warning \
    INFO replication | grep "master_repl_offset" | cut -d: -f2 | tr -d '\r')
REPLICA_OFFSET=$(redis-cli -p $REPLICA_PORT -a $REDIS_PASSWORD --no-auth-warning \
    INFO replication | grep "slave_repl_offset" | cut -d: -f2 | tr -d '\r')
DELAY=$((MASTER_OFFSET - REPLICA_OFFSET))
echo "Master offset: $MASTER_OFFSET"
echo "Replica offset: $REPLICA_OFFSET"
echo "复制延迟: $DELAY bytes"

# 5. Sentinel 健康检查
echo ""
echo "5. Sentinel 健康检查..."
SENTINEL_COUNT=$(redis-cli -p $SENTINEL_BASE_PORT SENTINEL sentinels $MASTER_NAME 2>/dev/null | grep "name" | wc -l)
SENTINEL_COUNT=$((SENTINEL_COUNT + 1))  # 加上当前连接的 Sentinel
echo "✓ 活跃的 Sentinel 数量: $SENTINEL_COUNT"

# 6. 故障转移测试提示
echo ""
echo "=========================================="
echo "测试完成"
echo "=========================================="
echo ""
echo "如需测试故障转移,执行以下命令:"
echo "1. 停止当前 Master:"
echo "   redis-cli -p $MASTER_PORT -a $REDIS_PASSWORD shutdown"
echo ""
echo "2. 观察 Sentinel 日志:"
echo "   tail -f redis-ha/sentinel-$SENTINEL_BASE_PORT.log"
echo ""
echo "3. 查看新的 Master:"
echo "   redis-cli -p $SENTINEL_BASE_PORT SENTINEL get-master-addr-by-name $MASTER_NAME"
echo ""
echo "4. 重新启动被停止的实例(它会自动变为 Replica):"
echo "   redis-server redis-ha/redis-$MASTER_PORT.conf"
echo "=========================================="
EOF

chmod +x test_redis_ha.sh
echo "✓ 测试脚本创建完成"

echo ""
echo "=========================================="
echo "所有脚本已创建完成!"
echo "=========================================="
echo ""
echo "💡 提示: 运行 ./test_redis_ha.sh 可测试环境是否正常工作"

Redis Cluster 集群模式一键部署脚本

#!/bin/bash

# ================================================
# Redis Cluster 集群模式一键部署脚本
# ================================================

# --- 1. 定义基础配置 ---
CLUSTER_BASE_PORT=7000             # Redis 集群起始端口
NODE_COUNT=6                       # 集群节点数量(建议至少 6 个:3主3从)
WORK_DIR="redis-cluster"           # 所有配置与数据存放的目录
CLUSTER_PASSWORD="hanserwei"       # 集群密码

# 获取工作目录的绝对路径
ABSOLUTE_WORK_DIR=$(pwd)/$WORK_DIR

echo "=========================================="
echo "Redis Cluster 集群部署脚本"
echo "=========================================="
echo "节点数量: $NODE_COUNT"
echo "起始端口: $CLUSTER_BASE_PORT"
echo "工作目录: $ABSOLUTE_WORK_DIR"
echo "=========================================="

# --- 2. 检查 Redis 是否安装 ---
if ! command -v redis-server &> /dev/null; then
    echo "错误: 未检测到 redis-server,请先安装 Redis"
    exit 1
fi

if ! command -v redis-cli &> /dev/null; then
    echo "错误: 未检测到 redis-cli,请先安装 Redis"
    exit 1
fi

echo "✓ Redis 已安装"

# --- 3. 清理并创建工作目录 ---
if [ -d "$WORK_DIR" ]; then
    echo ""
    read -p "检测到旧的 $WORK_DIR 目录,是否清理? (y/n): " confirm
    if [ "$confirm" = "y" ]; then
        echo "清理旧的 $WORK_DIR 目录..."
        # 停止所有相关进程
        for port in $(seq $CLUSTER_BASE_PORT $((CLUSTER_BASE_PORT + NODE_COUNT - 1))); do
            redis-cli -p $port -a $CLUSTER_PASSWORD --no-auth-warning shutdown 2>/dev/null
        done
        sleep 1
        rm -rf $WORK_DIR
    else
        echo "取消部署"
        exit 0
    fi
fi

mkdir -p $WORK_DIR
echo "✓ 创建工作目录: $ABSOLUTE_WORK_DIR"

# --- 4. 创建 Redis 集群节点配置文件 ---
echo ""
echo "--- 创建 Redis 集群节点配置 ---"
for i in $(seq 0 $((NODE_COUNT - 1))); do
    PORT=$((CLUSTER_BASE_PORT + i))
    NODE_DIR="$ABSOLUTE_WORK_DIR/node-$PORT"
    CONF_FILE="$NODE_DIR/redis.conf"

    # 创建节点目录
    mkdir -p "$NODE_DIR"

    echo "创建节点配置: node-$PORT"
    cat > "$CONF_FILE" <<-EOF
# 基础配置
port $PORT
daemonize yes
pidfile $NODE_DIR/redis.pid
logfile "$NODE_DIR/redis.log"
dir $NODE_DIR
bind 0.0.0.0
protected-mode no

# 持久化配置
appendonly yes
appendfilename "appendonly.aof"
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb

# 集群配置
cluster-enabled yes
cluster-config-file $NODE_DIR/nodes.conf
cluster-node-timeout 5000
cluster-require-full-coverage no

# 安全配置
requirepass $CLUSTER_PASSWORD
masterauth $CLUSTER_PASSWORD

# 性能优化
maxmemory 256mb
maxmemory-policy allkeys-lru
EOF
done

echo "✓ 配置文件创建完成"

# --- 5. 启动所有 Redis 节点 ---
echo ""
echo "--- 启动 Redis 集群节点 ---"
for i in $(seq 0 $((NODE_COUNT - 1))); do
    PORT=$((CLUSTER_BASE_PORT + i))
    NODE_DIR="$ABSOLUTE_WORK_DIR/node-$PORT"
    echo "启动节点 $PORT..."
    redis-server "$NODE_DIR/redis.conf"

    if [ $? -eq 0 ]; then
        echo "✓ 节点 $PORT 启动成功"
    else
        echo "✗ 节点 $PORT 启动失败"
        exit 1
    fi
done

sleep 2

# --- 6. 验证节点是否正常运行 ---
echo ""
echo "--- 验证节点状态 ---"
all_running=true
for i in $(seq 0 $((NODE_COUNT - 1))); do
    PORT=$((CLUSTER_BASE_PORT + i))
    if redis-cli -p $PORT -a $CLUSTER_PASSWORD --no-auth-warning ping > /dev/null 2>&1; then
        echo "✓ 节点 $PORT: 运行正常"
    else
        echo "✗ 节点 $PORT: 运行异常"
        all_running=false
    fi
done

if [ "$all_running" = false ]; then
    echo "部分节点启动失败,请检查日志"
    exit 1
fi

# --- 7. 创建集群 ---
echo ""
echo "--- 创建 Redis 集群 ---"
echo "正在将节点组建为集群(3主3从模式)..."

# 构建节点列表
CLUSTER_NODES=""
for i in $(seq 0 $((NODE_COUNT - 1))); do
    PORT=$((CLUSTER_BASE_PORT + i))
    CLUSTER_NODES="$CLUSTER_NODES 127.0.0.1:$PORT"
done

# 创建集群(自动分配主从关系)
echo "执行集群创建命令..."
redis-cli --cluster create $CLUSTER_NODES \
    --cluster-replicas 1 \
    -a $CLUSTER_PASSWORD \
    --cluster-yes

if [ $? -eq 0 ]; then
    echo "✓ 集群创建成功"
else
    echo "✗ 集群创建失败"
    exit 1
fi

sleep 2

# --- 8. 验证集群状态 ---
echo ""
echo "--- 验证集群状态 ---"
redis-cli -p $CLUSTER_BASE_PORT -a $CLUSTER_PASSWORD --no-auth-warning cluster info

echo ""
echo "--- 集群节点信息 ---"
redis-cli -p $CLUSTER_BASE_PORT -a $CLUSTER_PASSWORD --no-auth-warning cluster nodes

# --- 9. 输出部署信息 ---
echo ""
echo "=========================================="
echo "✓ Redis 集群部署完成!"
echo "=========================================="
echo "集群节点端口:"
for i in $(seq 0 $((NODE_COUNT - 1))); do
    PORT=$((CLUSTER_BASE_PORT + i))
    echo "  - 127.0.0.1:$PORT"
done
echo ""
echo "集群密码: $CLUSTER_PASSWORD"
echo "工作目录: $ABSOLUTE_WORK_DIR"
echo ""
echo "=========================================="
echo "常用操作命令:"
echo "=========================================="
echo "1. 连接到集群:"
echo "   redis-cli -c -p $CLUSTER_BASE_PORT -a $CLUSTER_PASSWORD"
echo ""
echo "2. 查看集群信息:"
echo "   redis-cli -p $CLUSTER_BASE_PORT -a $CLUSTER_PASSWORD cluster info"
echo ""
echo "3. 查看节点信息:"
echo "   redis-cli -p $CLUSTER_BASE_PORT -a $CLUSTER_PASSWORD cluster nodes"
echo ""
echo "4. 检查集群健康:"
echo "   redis-cli --cluster check 127.0.0.1:$CLUSTER_BASE_PORT -a $CLUSTER_PASSWORD"
echo ""
echo "5. 停止集群:"
echo "   ./stop_redis_cluster.sh"
echo "=========================================="

# --- 10. 创建停止脚本 ---
echo ""
echo "创建停止脚本 stop_redis_cluster.sh..."
cat > stop_redis_cluster.sh <<-EOF
#!/bin/bash

echo "=========================================="
echo "停止 Redis 集群"
echo "=========================================="

# 停止所有节点
for port in \$(seq $CLUSTER_BASE_PORT \$(($CLUSTER_BASE_PORT + $NODE_COUNT - 1))); do
    echo "停止节点 \$port..."
    redis-cli -p \$port -a $CLUSTER_PASSWORD --no-auth-warning shutdown 2>/dev/null
    if [ \$? -eq 0 ]; then
        echo "✓ 节点 \$port 已停止"
    else
        echo "✗ 节点 \$port 停止失败或未运行"
    fi
done

sleep 1

# 询问是否删除数据
read -p "是否删除集群数据目录 $WORK_DIR? (y/n): " confirm
if [ "\$confirm" = "y" ]; then
    echo "删除工作目录 $WORK_DIR..."
    rm -rf $WORK_DIR
    echo "✓ 清理完成"
else
    echo "保留数据目录"
fi

echo "=========================================="
echo "集群已停止"
echo "=========================================="
EOF

chmod +x stop_redis_cluster.sh
echo "✓ 停止脚本创建完成"

# --- 11. 创建测试脚本 ---
echo ""
echo "创建测试脚本 test_redis_cluster.sh..."
cat > test_redis_cluster.sh <<-EOF
#!/bin/bash

echo "=========================================="
echo "测试 Redis 集群"
echo "=========================================="

PORT=$CLUSTER_BASE_PORT
PASSWORD=$CLUSTER_PASSWORD

echo ""
echo "1. 写入测试数据..."
for i in {1..10}; do
    redis-cli -c -p \$PORT -a \$PASSWORD --no-auth-warning set "test_key_\$i" "value_\$i" > /dev/null
    echo "✓ 写入 test_key_\$i"
done

echo ""
echo "2. 读取测试数据..."
for i in {1..10}; do
    value=\$(redis-cli -c -p \$PORT -a \$PASSWORD --no-auth-warning get "test_key_\$i")
    echo "✓ test_key_\$i = \$value"
done

echo ""
echo "3. 查看键分布..."
for port in \$(seq $CLUSTER_BASE_PORT \$(($CLUSTER_BASE_PORT + $NODE_COUNT - 1))); do
    count=\$(redis-cli -p \$port -a \$PASSWORD --no-auth-warning dbsize)
    echo "节点 \$port: \$count 个键"
done

echo ""
echo "=========================================="
echo "测试完成"
echo "=========================================="
EOF

chmod +x test_redis_cluster.sh
echo "✓ 测试脚本创建完成"

echo ""
echo "=========================================="
echo "所有脚本已创建完成!"
echo "=========================================="