Java后端必须的Docker 部署 Redis 集群完整指南

Docker 部署 Redis 集群完整指南

一、Redis 集群架构设计

1.1 集群架构

scss 复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                    Redis Cluster (6节点)                             │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Master1(7001) ──── Slave1(7004)   Master2(7002) ──── Slave2(7005)  │
│         │                  │              │                  │      │
│  ───────┴──────────────────┴──────────────┴──────────────────┴──────│
│                                                                     │
│  Master3(7003) ──── Slave3(7006)                                   │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

二、Docker Compose 部署方案

2.1 docker-compose.yml

bash 复制代码
version: '3.8'

services:
  # Redis 节点 1 (主节点)
  redis-node-1:
    image: redis:7.2-alpine
    container_name: redis-cluster-node-1
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --appendonly yes
      --appendfsync everysec
      --save 900 1
      --save 300 10
      --save 60 10000
      --requirepass ${REDIS_PASSWORD:-Redis123456}
      --masterauth ${REDIS_PASSWORD:-Redis123456}
      --maxmemory 2gb
      --maxmemory-policy allkeys-lru
      --loglevel notice
      --logfile /data/redis.log
      --protected-mode no
    ports:
      - "7001:6379"
      - "17001:16379"  # 集群总线端口
    volumes:
      - redis-data-1:/data
      - ./redis.conf:/usr/local/etc/redis/redis.conf
      - ./logs/redis-node-1:/var/log/redis
    environment:
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD:-Redis123456}
      - REDIS_CLUSTER_REPLICAS=1
    networks:
      redis-cluster-network:
        ipv4_address: 172.20.0.11
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-Redis123456}", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    deploy:
      resources:
        limits:
          memory: 2G
        reservations:
          memory: 1G
    restart: unless-stopped

  # Redis 节点 2 (主节点)
  redis-node-2:
    image: redis:7.2-alpine
    container_name: redis-cluster-node-2
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --appendonly yes
      --appendfsync everysec
      --save 900 1
      --save 300 10
      --save 60 10000
      --requirepass ${REDIS_PASSWORD:-Redis123456}
      --masterauth ${REDIS_PASSWORD:-Redis123456}
      --maxmemory 2gb
      --maxmemory-policy allkeys-lru
      --loglevel notice
      --logfile /data/redis.log
      --protected-mode no
    ports:
      - "7002:6379"
      - "17002:16379"
    volumes:
      - redis-data-2:/data
      - ./redis.conf:/usr/local/etc/redis/redis.conf
      - ./logs/redis-node-2:/var/log/redis
    environment:
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD:-Redis123456}
    networks:
      redis-cluster-network:
        ipv4_address: 172.20.0.12
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-Redis123456}", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    restart: unless-stopped

  # Redis 节点 3 (主节点)
  redis-node-3:
    image: redis:7.2-alpine
    container_name: redis-cluster-node-3
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --appendonly yes
      --appendfsync everysec
      --save 900 1
      --save 300 10
      --save 60 10000
      --requirepass ${REDIS_PASSWORD:-Redis123456}
      --masterauth ${REDIS_PASSWORD:-Redis123456}
      --maxmemory 2gb
      --maxmemory-policy allkeys-lru
      --loglevel notice
      --logfile /data/redis.log
      --protected-mode no
    ports:
      - "7003:6379"
      - "17003:16379"
    volumes:
      - redis-data-3:/data
      - ./redis.conf:/usr/local/etc/redis/redis.conf
      - ./logs/redis-node-3:/var/log/redis
    environment:
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD:-Redis123456}
    networks:
      redis-cluster-network:
        ipv4_address: 172.20.0.13
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-Redis123456}", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    restart: unless-stopped

  # Redis 节点 4 (从节点)
  redis-node-4:
    image: redis:7.2-alpine
    container_name: redis-cluster-node-4
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --appendonly yes
      --appendfsync everysec
      --save 900 1
      --save 300 10
      --save 60 10000
      --requirepass ${REDIS_PASSWORD:-Redis123456}
      --masterauth ${REDIS_PASSWORD:-Redis123456}
      --maxmemory 2gb
      --maxmemory-policy allkeys-lru
      --loglevel notice
      --logfile /data/redis.log
      --protected-mode no
    ports:
      - "7004:6379"
      - "17004:16379"
    volumes:
      - redis-data-4:/data
      - ./redis.conf:/usr/local/etc/redis/redis.conf
      - ./logs/redis-node-4:/var/log/redis
    environment:
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD:-Redis123456}
    networks:
      redis-cluster-network:
        ipv4_address: 172.20.0.14
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-Redis123456}", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    restart: unless-stopped

  # Redis 节点 5 (从节点)
  redis-node-5:
    image: redis:7.2-alpine
    container_name: redis-cluster-node-5
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --appendonly yes
      --appendfsync everysec
      --save 900 1
      --save 300 10
      --save 60 10000
      --requirepass ${REDIS_PASSWORD:-Redis123456}
      --masterauth ${REDIS_PASSWORD:-Redis123456}
      --maxmemory 2gb
      --maxmemory-policy allkeys-lru
      --loglevel notice
      --logfile /data/redis.log
      --protected-mode no
    ports:
      - "7005:6379"
      - "17005:16379"
    volumes:
      - redis-data-5:/data
      - ./redis.conf:/usr/local/etc/redis/redis.conf
      - ./logs/redis-node-5:/var/log/redis
    environment:
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD:-Redis123456}
    networks:
      redis-cluster-network:
        ipv4_address: 172.20.0.15
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-Redis123456}", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    restart: unless-stopped

  # Redis 节点 6 (从节点)
  redis-node-6:
    image: redis:7.2-alpine
    container_name: redis-cluster-node-6
    command: >
      redis-server
      --bind 0.0.0.0
      --port 6379
      --cluster-enabled yes
      --cluster-config-file nodes.conf
      --cluster-node-timeout 5000
      --appendonly yes
      --appendfsync everysec
      --save 900 1
      --save 300 10
      --save 60 10000
      --requirepass ${REDIS_PASSWORD:-Redis123456}
      --masterauth ${REDIS_PASSWORD:-Redis123456}
      --maxmemory 2gb
      --maxmemory-policy allkeys-lru
      --loglevel notice
      --logfile /data/redis.log
      --protected-mode no
    ports:
      - "7006:6379"
      - "17006:16379"
    volumes:
      - redis-data-6:/data
      - ./redis.conf:/usr/local/etc/redis/redis.conf
      - ./logs/redis-node-6:/var/log/redis
    environment:
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD:-Redis123456}
    networks:
      redis-cluster-network:
        ipv4_address: 172.20.0.16
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD:-Redis123456}", "ping"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    restart: unless-stopped

  # Redis Cluster 初始化服务
  redis-cluster-init:
    image: redis:7.2-alpine
    container_name: redis-cluster-init
    depends_on:
      - redis-node-1
      - redis-node-2
      - redis-node-3
      - redis-node-4
      - redis-node-5
      - redis-node-6
    networks:
      - redis-cluster-network
    command: >
      sh -c "
      echo '等待Redis节点启动...';
      sleep 30;
      
      echo '检查节点健康状态...';
      for i in $$(seq 1 6); do
        redis-cli -h 172.20.0.1$$i -p 6379 -a ${REDIS_PASSWORD:-Redis123456} ping 2>/dev/null || echo '节点 $$i 未就绪';
      done;
      
      echo '创建Redis集群...';
      echo 'yes' | redis-cli --cluster create 
        172.20.0.11:6379 
        172.20.0.12:6379 
        172.20.0.13:6379 
        172.20.0.14:6379 
        172.20.0.15:6379 
        172.20.0.16:6379 
        --cluster-replicas 1 
        -a ${REDIS_PASSWORD:-Redis123456};
      
      echo '验证集群状态...';
      redis-cli --cluster check 172.20.0.11:6379 -a ${REDIS_PASSWORD:-Redis123456};
      
      echo '集群信息:';
      redis-cli -h 172.20.0.11 -p 6379 -a ${REDIS_PASSWORD:-Redis123456} cluster info;
      
      echo '节点信息:';
      redis-cli -h 172.20.0.11 -p 6379 -a ${REDIS_PASSWORD:-Redis123456} cluster nodes;
      
      echo 'Redis集群初始化完成!';
      "
    restart: on-failure

  # Redis 集群管理工具
  redis-commander:
    image: rediscommander/redis-commander:latest
    container_name: redis-cluster-web
    ports:
      - "8081:8081"
    environment:
      - REDIS_HOSTS=local:redis-node-1:6379:0:Redis123456,local:redis-node-2:6379:0:Redis123456,local:redis-node-3:6379:0:Redis123456
      - HTTP_USER=admin
      - HTTP_PASSWORD=${REDIS_PASSWORD:-Redis123456}
      - REDIS_PORT=6379
      - REDIS_PASSWORD=${REDIS_PASSWORD:-Redis123456}
    depends_on:
      - redis-cluster-init
    networks:
      - redis-cluster-network
    restart: unless-stopped

  # Redis 监控工具
  redis-exporter:
    image: oliver006/redis_exporter:latest
    container_name: redis-cluster-exporter
    ports:
      - "9121:9121"
    command:
      - '--redis.addr=redis://redis-node-1:6379'
      - '--redis.addr=redis://redis-node-2:6379'
      - '--redis.addr=redis://redis-node-3:6379'
      - '--redis.password=${REDIS_PASSWORD:-Redis123456}'
      - '--log-format=json'
      - '--namespace=redis_cluster'
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:-Redis123456}
    depends_on:
      - redis-cluster-init
    networks:
      - redis-cluster-network
    restart: unless-stopped

networks:
  redis-cluster-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16
          gateway: 172.20.0.1

volumes:
  redis-data-1:
    driver: local
  redis-data-2:
    driver: local
  redis-data-3:
    driver: local
  redis-data-4:
    driver: local
  redis-data-5:
    driver: local
  redis-data-6:
    driver: local

2.2 环境变量配置 (.env)

ini 复制代码
# Redis 集群环境变量配置
REDIS_PASSWORD=Redis123456@Cluster
REDIS_CLUSTER_NAME=production-cluster
REDIS_MAXMEMORY=2gb
REDIS_TIMEOUT=5000
REDIS_APPENDONLY=yes
REDIS_APPENDFSYNC=everysec

# 网络配置
REDIS_CLUSTER_SUBNET=172.20.0.0/16
REDIS_CLUSTER_GATEWAY=172.20.0.1

# 监控配置
PROMETHEUS_ENABLED=true
GRAFANA_ENABLED=true

# 端口映射
REDIS_PORT_START=7001
REDIS_CLUSTER_BUS_PORT_START=17001
REDIS_COMMANDER_PORT=8081
REDIS_EXPORTER_PORT=9121

三、自定义 Redis 配置文件

3.1 redis.conf

bash 复制代码
# Redis 集群配置文件
# 基于 Redis 7.2 版本

# 网络配置
bind 0.0.0.0
protected-mode no
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300

# 常规配置
daemonize no
pidfile /var/run/redis_6379.pid
loglevel notice
logfile /data/redis.log
databases 16
always-show-logo yes
set-proc-title yes
proc-title-template "{title} {listen-addr} {server-mode}"

# 快照配置
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
rdb-del-sync-files no
dir /data

# 主从复制配置
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-diskless-load disabled
repl-disable-tcp-nodelay no
replica-priority 100
acllog-max-len 128

# 安全配置
requirepass ${REDIS_PASSWORD}
masterauth ${REDIS_PASSWORD}

# 客户端配置
maxclients 10000
maxmemory 2gb
maxmemory-policy allkeys-lru
maxmemory-samples 5
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
lazyfree-lazy-user-del no
oom-score-adj no
oom-score-adj-values 0 200 800

# 持久化配置
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes

# Lua 脚本配置
lua-time-limit 5000

# 慢查询日志
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0

# 事件通知
notify-keyspace-events ""

# 高级配置
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
jemalloc-bg-thread yes

# 集群配置
cluster-enabled yes
cluster-config-file /data/nodes.conf
cluster-node-timeout 5000
cluster-replica-validity-factor 10
cluster-migration-barrier 1
cluster-require-full-coverage yes
cluster-replica-no-failover no
cluster-allow-reads-when-down no
cluster-allow-pubsubshard-when-down no
cluster-link-sendbuf-limit 0
cluster-announce-ip ${HOST_IP}
cluster-announce-port 6379
cluster-announce-bus-port 16379

# 模块配置
loadmodule /usr/lib/redis/modules/redisearch.so
loadmodule /usr/lib/redis/modules/rejson.so
loadmodule /usr/lib/redis/modules/redisgraph.so
loadmodule /usr/lib/redis/modules/redistimeseries.so
loadmodule /usr/lib/redis/modules/redisbloom.so

# TLS/SSL 配置
# tls-port 0
# tls-cert-file /etc/redis/certs/redis.crt
# tls-key-file /etc/redis/certs/redis.key
# tls-ca-cert-file /etc/redis/certs/ca.crt
# tls-auth-clients no
# tls-auth-clients optional
# tls-protocols "TLSv1.2 TLSv1.3"
# tls-ciphers DEFAULT:!MEDIUM
# tls-ciphersuites TLS_CHACHA20_POLY1305_SHA256
# tls-prefer-server-ciphers yes
# tls-session-caching no
# tls-session-cache-size 20480
# tls-session-cache-timeout 300

四、启动和部署脚本

4.1 启动脚本 (start-cluster.sh)

bash 复制代码
#!/bin/bash

# Redis Cluster 启动脚本
# 支持 Docker 和 Docker Compose 部署

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 检查依赖
check_dependencies() {
    log_info "检查系统依赖..."
    
    # 检查 Docker
    if ! command -v docker &> /dev/null; then
        log_error "Docker 未安装"
        exit 1
    fi
    
    # 检查 Docker Compose
    if ! command -v docker-compose &> /dev/null; then
        log_error "Docker Compose 未安装"
        exit 1
    fi
    
    log_success "依赖检查通过"
}

# 创建目录结构
create_directories() {
    log_info "创建目录结构..."
    
    mkdir -p ./data/{node1,node2,node3,node4,node5,node6}
    mkdir -p ./logs/{node1,node2,node3,node4,node5,node6}
    mkdir -p ./config
    mkdir -p ./ssl
    
    log_success "目录创建完成"
}

# 生成配置文件
generate_configs() {
    log_info "生成 Redis 配置文件..."
    
    # 生成主配置文件
    cat > ./config/redis.conf << 'EOF'
# Redis 集群配置文件
bind 0.0.0.0
port 6379
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
requirepass ${REDIS_PASSWORD}
masterauth ${REDIS_PASSWORD}
EOF
    
    # 生成节点配置文件
    for i in {1..6}; do
        cat > ./config/redis-node-$i.conf << EOF
# Redis 节点 $i 配置
bind 0.0.0.0
port 6379
cluster-enabled yes
cluster-config-file /data/nodes.conf
cluster-node-timeout 5000
appendonly yes
appendfilename &#34;appendonly-node-$i.aof&#34;
dbfilename &#34;dump-node-$i.rdb&#34;
dir /data
requirepass ${REDIS_PASSWORD:-Redis123456}
masterauth ${REDIS_PASSWORD:-Redis123456}
maxmemory 2gb
maxmemory-policy allkeys-lru
loglevel notice
logfile /var/log/redis/redis.log
protected-mode no
EOF
    done
    
    log_success &#34;配置文件生成完成&#34;
}

# 启动 Redis 集群
start_cluster() {
    log_info &#34;启动 Redis 集群...&#34;
    
    # 加载环境变量
    if [ -f .env ]; then
        log_info &#34;加载环境变量...&#34;
        export $(grep -v '^#' .env | xargs)
    fi
    
    # 启动集群
    docker-compose up -d
    
    # 等待集群启动
    log_info &#34;等待集群启动...&#34;
    sleep 10
    
    # 检查集群状态
    check_cluster_health
    
    log_success &#34;Redis 集群启动完成&#34;
}

# 检查集群健康状态
check_cluster_health() {
    log_info &#34;检查集群健康状态...&#34;
    
    local retries=10
    local wait_time=5
    
    for ((i=1; i<=retries; i++)); do
        log_info &#34;尝试 $i/$retries 检查集群状态...&#34;
        
        # 检查节点是否可访问
        if docker exec redis-cluster-node-1 redis-cli -a &#34;${REDIS_PASSWORD:-Redis123456}&#34; ping 2>/dev/null | grep -q &#34;PONG&#34;; then
            # 获取集群信息
            local cluster_info=$(docker exec redis-cluster-node-1 redis-cli -a &#34;${REDIS_PASSWORD:-Redis123456}&#34; cluster info 2>/dev/null)
            
            if echo &#34;$cluster_info&#34; | grep -q &#34;cluster_state:ok&#34;; then
                log_success &#34;集群状态正常&#34;
                
                # 显示集群信息
                echo &#34;========================================&#34;
                echo &#34;Redis 集群信息:&#34;
                echo &#34;========================================&#34;
                docker exec redis-cluster-node-1 redis-cli -a &#34;${REDIS_PASSWORD:-Redis123456}&#34; cluster info
                echo &#34;========================================&#34;
                echo &#34;集群节点:&#34;
                docker exec redis-cluster-node-1 redis-cli -a &#34;${REDIS_PASSWORD:-Redis123456}&#34; cluster nodes
                echo &#34;========================================&#34;
                
                return 0
            fi
        fi
        
        if [ $i -lt $retries ]; then
            log_info &#34;等待 ${wait_time} 秒后重试...&#34;
            sleep $wait_time
        fi
    done
    
    log_error &#34;集群健康检查失败&#34;
    return 1
}

# 停止集群
stop_cluster() {
    log_info &#34;停止 Redis 集群...&#34;
    docker-compose down
    log_success &#34;Redis 集群已停止&#34;
}

# 重启集群
restart_cluster() {
    log_info &#34;重启 Redis 集群...&#34;
    stop_cluster
    sleep 5
    start_cluster
}

# 清理集群
clean_cluster() {
    log_warn &#34;清理 Redis 集群数据...&#34;
    read -p &#34;确认要删除所有数据吗?(y/n): &#34; -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        docker-compose down -v
        rm -rf ./data/* ./logs/*
        log_success &#34;集群数据已清理&#34;
    else
        log_info &#34;取消清理操作&#34;
    fi
}

# 集群扩容
scale_cluster() {
    log_info &#34;集群扩容...&#34;
    
    echo &#34;选择扩容方式:&#34;
    echo &#34;1) 增加主节点&#34;
    echo &#34;2) 增加从节点&#34;
    echo &#34;3) 退出&#34;
    
    read -p &#34;请选择 (1-3): &#34; choice
    
    case $choice in
        1)
            add_master_node
            ;;
        2)
            add_slave_node
            ;;
        3)
            log_info &#34;退出扩容&#34;
            ;;
        *)
            log_error &#34;无效选择&#34;
            ;;
    esac
}

# 添加主节点
add_master_node() {
    log_info &#34;添加主节点...&#34;
    
    # 获取下一个节点编号
    local next_node=$(($(ls -d ./data/node* 2>/dev/null | wc -l) + 1))
    
    # 创建数据目录
    mkdir -p ./data/node$next_node
    mkdir -p ./logs/node$next_node
    
    # 生成节点配置
    cat > ./config/redis-node-$next_node.conf << EOF
bind 0.0.0.0
port 6379
cluster-enabled yes
cluster-config-file /data/nodes.conf
cluster-node-timeout 5000
appendonly yes
dir /data
requirepass ${REDIS_PASSWORD:-Redis123456}
masterauth ${REDIS_PASSWORD:-Redis123456}
EOF
    
    # 更新 docker-compose.yml
    # 这里需要手动更新 docker-compose.yml 文件
    
    log_warn &#34;请手动更新 docker-compose.yml 文件添加新节点&#34;
    log_info &#34;然后运行: docker-compose up -d redis-node-$next_node&#34;
    log_info &#34;最后将新节点加入集群: docker exec redis-cluster-node-1 redis-cli --cluster add-node new_host:new_port existing_host:existing_port&#34;
}

# 备份集群
backup_cluster() {
    log_info &#34;备份集群数据...&#34;
    
    local backup_dir=&#34;./backups/$(date +%Y%m%d_%H%M%S)&#34;
    mkdir -p &#34;$backup_dir&#34;
    
    # 备份数据
    for i in {1..6}; do
        if docker ps | grep -q &#34;redis-cluster-node-$i&#34;; then
            log_info &#34;备份节点 $i 数据...&#34;
            docker exec redis-cluster-node-$i redis-cli -a &#34;${REDIS_PASSWORD:-Redis123456}&#34; save
            cp -r ./data/node$i &#34;$backup_dir/&#34;
        fi
    done
    
    # 备份配置
    cp -r ./config &#34;$backup_dir/&#34;
    cp docker-compose.yml &#34;$backup_dir/&#34;
    cp .env &#34;$backup_dir/&#34; 2>/dev/null || true
    
    # 创建备份元数据
    cat > &#34;$backup_dir/backup.info&#34; << EOF
备份时间: $(date)
集群节点: 6
Redis 版本: 7.2
备份目录: $backup_dir
EOF
    
    # 压缩备份
    tar -czf &#34;$backup_dir.tar.gz&#34; -C ./backups &#34;$(basename $backup_dir)&#34;
    
    log_success &#34;集群备份完成: $backup_dir.tar.gz&#34;
}

# 监控集群
monitor_cluster() {
    log_info &#34;启动集群监控...&#34;
    
    echo &#34;选择监控方式:&#34;
    echo &#34;1) 实时监控&#34;
    echo &#34;2) 查看节点信息&#34;
    echo &#34;3) 查看内存使用&#34;
    echo &#34;4) 查看慢查询&#34;
    echo &#34;5) 返回&#34;
    
    read -p &#34;请选择 (1-5): &#34; choice
    
    case $choice in
        1)
            docker exec -it redis-cluster-node-1 redis-cli -a &#34;${REDIS_PASSWORD:-Redis123456}&#34; --stat
            ;;
        2)
            docker exec redis-cluster-node-1 redis-cli -a &#34;${REDIS_PASSWORD:-Redis123456}&#34; cluster nodes
            ;;
        3)
            docker exec redis-cluster-node-1 redis-cli -a &#34;${REDIS_PASSWORD:-Redis123456}&#34; info memory
            ;;
        4)
            docker exec redis-cluster-node-1 redis-cli -a &#34;${REDIS_PASSWORD:-Redis123456}&#34; slowlog get 10
            ;;
        5)
            return
            ;;
        *)
            log_error &#34;无效选择&#34;
            ;;
    esac
}

# 主菜单
show_menu() {
    clear
    echo &#34;========================================&#34;
    echo &#34;    Redis Cluster 管理工具&#34;
    echo &#34;========================================&#34;
    echo &#34;1) 启动集群&#34;
    echo &#34;2) 停止集群&#34;
    echo &#34;3) 重启集群&#34;
    echo &#34;4) 检查状态&#34;
    echo &#34;5) 集群扩容&#34;
    echo &#34;6) 备份集群&#34;
    echo &#34;7) 监控集群&#34;
    echo &#34;8) 清理集群&#34;
    echo &#34;9) 退出&#34;
    echo &#34;========================================&#34;
}

# 主函数
main() {
    # 检查依赖
    check_dependencies
    
    # 创建目录
    create_directories
    
    # 生成配置
    generate_configs
    
    while true; do
        show_menu
        read -p &#34;请选择操作 (1-9): &#34; choice
        
        case $choice in
            1)
                start_cluster
                ;;
            2)
                stop_cluster
                ;;
            3)
                restart_cluster
                ;;
            4)
                check_cluster_health
                ;;
            5)
                scale_cluster
                ;;
            6)
                backup_cluster
                ;;
            7)
                monitor_cluster
                ;;
            8)
                clean_cluster
                ;;
            9)
                log_info &#34;退出管理工具&#34;
                exit 0
                ;;
            *)
                log_error &#34;无效选择,请重新输入&#34;
                ;;
        esac
        
        read -p &#34;按 Enter 键继续...&#34;
    done
}

# 执行主函数
main &#34;$@&#34;

4.2 集群测试脚本 (test-cluster.sh)

bash 复制代码
#!/bin/bash

# Redis Cluster 测试脚本

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() { echo -e &#34;${BLUE}[INFO]${NC} $1&#34;; }
log_success() { echo -e &#34;${GREEN}[SUCCESS]${NC} $1&#34;; }
log_warn() { echo -e &#34;${YELLOW}[WARN]${NC} $1&#34;; }
log_error() { echo -e &#34;${RED}[ERROR]${NC} $1&#34;; }

# 加载环境变量
if [ -f .env ]; then
    export $(grep -v '^#' .env | xargs)
fi

REDIS_PASSWORD=${REDIS_PASSWORD:-Redis123456}
REDIS_HOST=${REDIS_HOST:-localhost}
PORTS=(7001 7002 7003 7004 7005 7006)

# 测试连接
test_connection() {
    log_info &#34;测试 Redis 集群连接...&#34;
    
    for port in &#34;${PORTS[@]}&#34;; do
        if redis-cli -h $REDIS_HOST -p $port -a &#34;$REDIS_PASSWORD&#34; ping 2>/dev/null | grep -q &#34;PONG&#34;; then
            log_success &#34;节点 $REDIS_HOST:$port 连接成功&#34;
        else
            log_error &#34;节点 $REDIS_HOST:$port 连接失败&#34;
            return 1
        fi
    done
    
    return 0
}

# 测试集群状态
test_cluster_status() {
    log_info &#34;测试集群状态...&#34;
    
    local cluster_info=$(redis-cli -h $REDIS_HOST -p 7001 -a &#34;$REDIS_PASSWORD&#34; cluster info 2>/dev/null)
    
    if echo &#34;$cluster_info&#34; | grep -q &#34;cluster_state:ok&#34;; then
        log_success &#34;集群状态正常&#34;
        echo &#34;$cluster_info&#34;
        return 0
    else
        log_error &#34;集群状态异常&#34;
        echo &#34;$cluster_info&#34;
        return 1
    fi
}

# 测试数据读写
test_data_operations() {
    log_info &#34;测试数据读写操作...&#34;
    
    local test_key=&#34;test:cluster:$(date +%s)&#34;
    local test_value=&#34;test_value_$(date +%s)&#34;
    
    # 写入数据
    if redis-cli -h $REDIS_HOST -p 7001 -a &#34;$REDIS_PASSWORD&#34; set &#34;$test_key&#34; &#34;$test_value&#34; 2>/dev/null | grep -q &#34;OK&#34;; then
        log_success &#34;数据写入成功: $test_key = $test_value&#34;
    else
        log_error &#34;数据写入失败&#34;
        return 1
    fi
    
    # 读取数据
    local read_value=$(redis-cli -h $REDIS_HOST -p 7001 -a &#34;$REDIS_PASSWORD&#34; get &#34;$test_key&#34; 2>/dev/null)
    
    if [ &#34;$read_value&#34; = &#34;$test_value&#34; ]; then
        log_success &#34;数据读取成功: $test_key = $read_value&#34;
    else
        log_error &#34;数据读取失败&#34;
        return 1
    fi
    
    # 删除数据
    if redis-cli -h $REDIS_HOST -p 7001 -a &#34;$REDIS_PASSWORD&#34; del &#34;$test_key&#34; 2>/dev/null | grep -q &#34;^1$&#34;; then
        log_success &#34;数据删除成功&#34;
    else
        log_error &#34;数据删除失败&#34;
        return 1
    fi
    
    return 0
}

# 测试集群重定向
test_cluster_redirect() {
    log_info &#34;测试集群重定向...&#34;
    
    # 创建多个键,确保它们分布在不同节点
    local keys=()
    for i in {1..100}; do
        keys+=(&#34;cluster:key:$i&#34;)
    done
    
    local success_count=0
    local fail_count=0
    
    for key in &#34;${keys[@]}&#34;; do
        # 尝试在随机节点上设置值
        local random_port=${PORTS[$RANDOM % ${#PORTS[@]}]}
        local result=$(redis-cli -h $REDIS_HOST -p $random_port -a &#34;$REDIS_PASSWORD&#34; set &#34;$key&#34; &#34;value_$key&#34; 2>&1)
        
        if echo &#34;$result&#34; | grep -q &#34;MOVED\|OK&#34;; then
            ((success_count++))
        else
            ((fail_count++))
            log_warn &#34;键 $key 在端口 $random_port 设置失败: $result&#34;
        fi
    done
    
    log_info &#34;重定向测试结果: 成功 $success_count, 失败 $fail_count&#34;
    
    if [ $fail_count -eq 0 ]; then
        log_success &#34;集群重定向测试通过&#34;
        return 0
    else
        log_error &#34;集群重定向测试失败&#34;
        return 1
    fi
}

# 测试故障转移
test_failover() {
    log_info &#34;测试故障转移(模拟主节点故障)...&#34;
    
    # 获取当前主节点
    local master_nodes=$(redis-cli -h $REDIS_HOST -p 7001 -a &#34;$REDIS_PASSWORD&#34; cluster nodes 2>/dev/null | grep &#34;master&#34; | head -3)
    local first_master=$(echo &#34;$master_nodes&#34; | head -1 | awk '{print $2}')
    
    if [ -z &#34;$first_master&#34; ]; then
        log_error &#34;无法获取主节点信息&#34;
        return 1
    fi
    
    local master_host=$(echo &#34;$first_master&#34; | cut -d: -f1)
    local master_port=$(echo &#34;$first_master&#34; | cut -d: -f2)
    
    log_info &#34;模拟主节点 $master_host:$master_port 故障...&#34;
    
    # 停止主节点容器
    local container_name=$(docker ps --format &#34;{{.Names}}&#34; | grep &#34;$master_port&#34; | head -1)
    
    if [ -n &#34;$container_name&#34; ]; then
        log_info &#34;停止容器: $container_name&#34;
        docker stop &#34;$container_name&#34;
        
        # 等待故障转移
        log_info &#34;等待故障转移 (30秒)...&#34;
        sleep 30
        
        # 检查新的主节点
        local new_master=$(redis-cli -h $REDIS_HOST -p 7002 -a &#34;$REDIS_PASSWORD&#34; cluster nodes 2>/dev/null | grep &#34;$master_host:$master_port&#34; | grep &#34;slave&#34;)
        
        if [ -n &#34;$new_master&#34; ]; then
            log_success &#34;故障转移成功: 原主节点 $master_host:$master_port 变为从节点&#34;
        else
            log_error &#34;故障转移失败&#34;
        fi
        
        # 恢复节点
        log_info &#34;恢复节点...&#34;
        docker start &#34;$container_name&#34;
        sleep 10
    else
        log_error &#34;未找到对应的容器&#34;
        return 1
    fi
    
    return 0
}

# 性能测试
test_performance() {
    log_info &#34;运行性能测试...&#34;
    
    # 使用 redis-benchmark 测试
    log_info &#34;1. 测试 SET 操作...&#34;
    redis-benchmark -h $REDIS_HOST -p 7001 -a &#34;$REDIS_PASSWORD&#34; -t set -n 10000 -c 50
    
    log_info &#34;2. 测试 GET 操作...&#34;
    redis-benchmark -h $REDIS_HOST -p 7001 -a &#34;$REDIS_PASSWORD&#34; -t get -n 10000 -c 50
    
    log_info &#34;3. 测试流水线操作...&#34;
    redis-benchmark -h $REDIS_HOST -p 7001 -a &#34;$REDIS_PASSWORD&#34; -t ping,set,get -n 10000 -c 50 -P 16
    
    log_success &#34;性能测试完成&#34;
}

# 运行所有测试
run_all_tests() {
    log_info &#34;开始 Redis 集群完整测试...&#34;
    
    local tests_passed=0
    local tests_failed=0
    
    # 测试1: 连接测试
    if test_connection; then
        ((tests_passed++))
    else
        ((tests_failed++))
    fi
    
    # 测试2: 集群状态测试
    if test_cluster_status; then
        ((tests_passed++))
    else
        ((tests_failed++))
    fi
    
    # 测试3: 数据操作测试
    if test_data_operations; then
        ((tests_passed++))
    else
        ((tests_failed++))
    fi
    
    # 测试4: 集群重定向测试
    if test_cluster_redirect; then
        ((tests_passed++))
    else
        ((tests_failed++))
    fi
    
    # 测试5: 性能测试
    test_performance
    
    echo &#34;========================================&#34;
    echo &#34;测试结果汇总:&#34;
    echo &#34;通过: $tests_passed&#34;
    echo &#34;失败: $tests_failed&#34;
    echo &#34;========================================&#34;
    
    if [ $tests_failed -eq 0 ]; then
        log_success &#34;所有测试通过!Redis 集群运行正常。&#34;
        return 0
    else
        log_error &#34;有 $tests_failed 个测试失败&#34;
        return 1
    fi
}

# 主函数
main() {
    echo &#34;========================================&#34;
    echo &#34;    Redis Cluster 测试工具&#34;
    echo &#34;========================================&#34;
    echo &#34;1) 运行完整测试&#34;
    echo &#34;2) 测试连接&#34;
    echo &#34;3) 测试集群状态&#34;
    echo &#34;4) 测试数据操作&#34;
    echo &#34;5) 测试集群重定向&#34;
    echo &#34;6) 测试故障转移&#34;
    echo &#34;7) 性能测试&#34;
    echo &#34;8) 退出&#34;
    echo &#34;========================================&#34;
    
    read -p &#34;请选择测试项目 (1-8): &#34; choice
    
    case $choice in
        1)
            run_all_tests
            ;;
        2)
            test_connection
            ;;
        3)
            test_cluster_status
            ;;
        4)
            test_data_operations
            ;;
        5)
            test_cluster_redirect
            ;;
        6)
            test_failover
            ;;
        7)
            test_performance
            ;;
        8)
            log_info &#34;退出测试工具&#34;
            exit 0
            ;;
        *)
            log_error &#34;无效选择&#34;
            exit 1
            ;;
    esac
}

# 执行主函数
main &#34;$@&#34;

五、Kubernetes 部署方案

5.1 Redis Cluster Kubernetes 部署文件

5.1.1 namespace.yaml
yaml 复制代码
apiVersion: v1
kind: Namespace
metadata:
  name: redis-cluster
  labels:
    name: redis-cluster
    component: database
    environment: production
5.1.2 configmap.yaml
arduino 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster-config
  namespace: redis-cluster
data:
  redis.conf: |
    # Redis 集群配置
    bind 0.0.0.0
    port 6379
    cluster-enabled yes
    cluster-config-file /data/nodes.conf
    cluster-node-timeout 5000
    cluster-slave-validity-factor 10
    cluster-migration-barrier 1
    cluster-require-full-coverage yes
    appendonly yes
    appendfilename &#34;appendonly.aof&#34;
    appendfsync everysec
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    dir /data
    save 900 1
    save 300 10
    save 60 10000
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes
    dbfilename dump.rdb
    maxmemory 2gb
    maxmemory-policy allkeys-lru
    maxmemory-samples 5
    lazyfree-lazy-eviction no
    lazyfree-lazy-expire no
    lazyfree-lazy-server-del no
    replica-lazy-flush no
    lua-time-limit 5000
    slowlog-log-slower-than 10000
    slowlog-max-len 128
    latency-monitor-threshold 0
    notify-keyspace-events &#34;&#34;
    hash-max-ziplist-entries 512
    hash-max-ziplist-value 64
    list-max-ziplist-size -2
    list-compress-depth 0
    set-max-intset-entries 512
    zset-max-ziplist-entries 128
    zset-max-ziplist-value 64
    hll-sparse-max-bytes 3000
    stream-node-max-bytes 4096
    stream-node-max-entries 100
    activerehashing yes
    client-output-buffer-limit normal 0 0 0
    client-output-buffer-limit replica 256mb 64mb 60
    client-output-buffer-limit pubsub 32mb 8mb 60
    hz 10
    dynamic-hz yes
    aof-rewrite-incremental-fsync yes
    rdb-save-incremental-fsync yes
5.1.3 secret.yaml
yaml 复制代码
apiVersion: v1
kind: Secret
metadata:
  name: redis-cluster-secret
  namespace: redis-cluster
type: Opaque
stringData:
  redis-password: &#34;Redis123456@K8s&#34;
  requirepass: &#34;Redis123456@K8s&#34;
  masterauth: &#34;Redis123456@K8s&#34;
5.1.4 service.yaml
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  name: redis-cluster
  namespace: redis-cluster
  labels:
    app: redis-cluster
    component: database
spec:
  ports:
  - name: client
    port: 6379
    targetPort: 6379
  - name: cluster
    port: 16379
    targetPort: 16379
  clusterIP: None
  selector:
    app: redis-cluster
---
apiVersion: v1
kind: Service
metadata:
  name: redis-cluster-headless
  namespace: redis-cluster
  labels:
    app: redis-cluster
    component: database
spec:
  ports:
  - name: client
    port: 6379
    targetPort: 6379
  - name: cluster
    port: 16379
    targetPort: 16379
  clusterIP: None
  selector:
    app: redis-cluster
5.1.5 statefulset.yaml
yaml 复制代码
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
  namespace: redis-cluster
  labels:
    app: redis-cluster
    component: database
    environment: production
spec:
  serviceName: redis-cluster-headless
  replicas: 6
  selector:
    matchLabels:
      app: redis-cluster
  updateStrategy:
    type: RollingUpdate
  podManagementPolicy: OrderedReady
  template:
    metadata:
      labels:
        app: redis-cluster
        component: database
        environment: production
      annotations:
        prometheus.io/scrape: &#34;true&#34;
        prometheus.io/port: &#34;9121&#34;
        prometheus.io/path: &#34;/metrics&#34;
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - redis-cluster
              topologyKey: kubernetes.io/hostname
      containers:
      - name: redis
        image: redis:7.2-alpine
        imagePullPolicy: IfNotPresent
        command:
        - redis-server
        - /etc/redis/redis.conf
        - --requirepass
        - $(REDIS_PASSWORD)
        - --masterauth
        - $(REDIS_PASSWORD)
        ports:
        - name: client
          containerPort: 6379
        - name: cluster
          containerPort: 16379
        env:
        - name: REDIS_PASSWORD
          valueFrom:
            secretKeyRef:
              name: redis-cluster-secret
              key: redis-password
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        resources:
          requests:
            memory: &#34;2Gi&#34;
            cpu: &#34;1000m&#34;
          limits:
            memory: &#34;4Gi&#34;
            cpu: &#34;2000m&#34;
        volumeMounts:
        - name: redis-config
          mountPath: /etc/redis
        - name: redis-data
          mountPath: /data
        - name: redis-tmp
          mountPath: /tmp
        livenessProbe:
          exec:
            command:
            - redis-cli
            - -a
            - $(REDIS_PASSWORD)
            - ping
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 5
          failureThreshold: 3
        readinessProbe:
          exec:
            command:
            - redis-cli
            - -a
            - $(REDIS_PASSWORD)
            - ping
          initialDelaySeconds: 5
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3
        startupProbe:
          exec:
            command:
            - redis-cli
            - -a
            - $(REDIS_PASSWORD)
            - ping
          initialDelaySeconds: 0
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 30
        securityContext:
          privileged: false
          readOnlyRootFilesystem: true
          allowPrivilegeEscalation: false
          capabilities:
            drop:
            - ALL
      volumes:
      - name: redis-config
        configMap:
          name: redis-cluster-config
      - name: redis-tmp
        emptyDir: {}
  volumeClaimTemplates:
  - metadata:
      name: redis-data
    spec:
      accessModes:
      - ReadWriteOnce
      storageClassName: standard
      resources:
        requests:
          storage: 20Gi
5.1.6 job-init.yaml
bash 复制代码
apiVersion: batch/v1
kind: Job
metadata:
  name: redis-cluster-init
  namespace: redis-cluster
spec:
  template:
    spec:
      containers:
      - name: redis-cluster-init
        image: redis:7.2-alpine
        command:
        - /bin/sh
        - -c
        - |
          echo &#34;等待 Redis 节点启动...&#34;
          sleep 30
          
          echo &#34;获取 Pod IP 地址...&#34;
          POD_IPS=()
          for i in {0..5}; do
            IP=$(getent hosts redis-cluster-$i.redis-cluster-headless.redis-cluster.svc.cluster.local | awk '{ print $1 }')
            if [ -n &#34;$IP&#34; ]; then
              POD_IPS+=(&#34;$IP:6379&#34;)
              echo &#34;节点 $i IP: $IP&#34;
            fi
          done
          
          echo &#34;创建 Redis 集群...&#34;
          echo &#34;yes&#34; | redis-cli --cluster create \
            ${POD_IPS[@]} \
            --cluster-replicas 1 \
            -a $(REDIS_PASSWORD)
          
          echo &#34;验证集群状态...&#34;
          redis-cli --cluster check ${POD_IPS[0]} -a $(REDIS_PASSWORD)
          
          echo &#34;集群信息:&#34;
          redis-cli -h ${POD_IPS[0]%:*} -p 6379 -a $(REDIS_PASSWORD) cluster info
          
          echo &#34;节点信息:&#34;
          redis-cli -h ${POD_IPS[0]%:*} -p 6379 -a $(REDIS_PASSWORD) cluster nodes
          
          echo &#34;Redis 集群初始化完成!&#34;
        env:
        - name: REDIS_PASSWORD
          valueFrom:
            secretKeyRef:
              name: redis-cluster-secret
              key: redis-password
      restartPolicy: OnFailure
  backoffLimit: 3
  activeDeadlineSeconds: 300

六、监控和告警配置

6.1 Prometheus 监控配置

yaml 复制代码
# prometheus-config.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: 'redis-cluster'
    static_configs:
      - targets:
        - 'redis-cluster-exporter:9121'
    metrics_path: /metrics
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
        regex: '(.*):.*'
        replacement: '${1}'

  - job_name: 'redis-cluster-nodes'
    kubernetes_sd_configs:
      - role: pod
        namespaces:
          names:
            - redis-cluster
    relabel_configs:
      - source_labels: [__meta_kubernetes_pod_label_app]
        regex: redis-cluster
        action: keep
      - source_labels: [__meta_kubernetes_pod_container_port_number]
        regex: 6379
        action: keep
      - source_labels: [__meta_kubernetes_pod_ip]
        target_label: instance
        replacement: '${1}:6379'
      - source_labels: [__meta_kubernetes_pod_name]
        target_label: pod
      - source_labels: [__meta_kubernetes_namespace]
        target_label: namespace

6.2 Grafana 仪表板

xml 复制代码
{
  &#34;dashboard&#34;: {
    &#34;id&#34;: null,
    &#34;title&#34;: &#34;Redis Cluster Monitoring&#34;,
    &#34;tags&#34;: [&#34;redis&#34;, &#34;cluster&#34;, &#34;database&#34;],
    &#34;timezone&#34;: &#34;browser&#34;,
    &#34;panels&#34;: [
      {
        &#34;id&#34;: 1,
        &#34;title&#34;: &#34;Cluster Health&#34;,
        &#34;type&#34;: &#34;stat&#34;,
        &#34;targets&#34;: [
          {
            &#34;expr&#34;: &#34;redis_up&#34;,
            &#34;legendFormat&#34;: &#34;{{instance}}&#34;
          }
        ],
        &#34;fieldConfig&#34;: {
          &#34;defaults&#34;: {
            &#34;thresholds&#34;: {
              &#34;steps&#34;: [
                {&#34;color&#34;: &#34;red&#34;, &#34;value&#34;: null},
                {&#34;color&#34;: &#34;green&#34;, &#34;value&#34;: 1}
              ]
            }
          }
        }
      },
      {
        &#34;id&#34;: 2,
        &#34;title&#34;: &#34;Memory Usage&#34;,
        &#34;type&#34;: &#34;graph&#34;,
        &#34;targets&#34;: [
          {
            &#34;expr&#34;: &#34;redis_memory_used_bytes / 1024 / 1024&#34;,
            &#34;legendFormat&#34;: &#34;Used Memory (MB) - {{instance}}&#34;
          },
          {
            &#34;expr&#34;: &#34;redis_memory_max_bytes / 1024 / 1024&#34;,
            &#34;legendFormat&#34;: &#34;Max Memory (MB) - {{instance}}&#34;
          }
        ]
      },
      {
        &#34;id&#34;: 3,
        &#34;title&#34;: &#34;Commands per Second&#34;,
        &#34;type&#34;: &#34;graph&#34;,
        &#34;targets&#34;: [
          {
            &#34;expr&#34;: &#34;rate(redis_commands_processed_total[5m])&#34;,
            &#34;legendFormat&#34;: &#34;Commands/s - {{instance}}&#34;
          }
        ]
      },
      {
        &#34;id&#34;: 4,
        &#34;title&#34;: &#34;Connections&#34;,
        &#34;type&#34;: &#34;graph&#34;,
        &#34;targets&#34;: [
          {
            &#34;expr&#34;: &#34;redis_connected_clients&#34;,
            &#34;legendFormat&#34;: &#34;Connected Clients - {{instance}}&#34;
          }
        ]
      },
      {
        &#34;id&#34;: 5,
        &#34;title&#34;: &#34;Keyspace&#34;,
        &#34;type&#34;: &#34;graph&#34;,
        &#34;targets&#34;: [
          {
            &#34;expr&#34;: &#34;redis_db_keys&#34;,
            &#34;legendFormat&#34;: &#34;Keys - db{{db}}&#34;
          }
        ]
      },
      {
        &#34;id&#34;: 6,
        &#34;title&#34;: &#34;CPU Usage&#34;,
        &#34;type&#34;: &#34;graph&#34;,
        &#34;targets&#34;: [
          {
            &#34;expr&#34;: &#34;rate(redis_cpu_sys_seconds_total[5m]) * 100&#34;,
            &#34;legendFormat&#34;: &#34;System CPU % - {{instance}}&#34;
          },
          {
            &#34;expr&#34;: &#34;rate(redis_cpu_user_seconds_total[5m]) * 100&#34;,
            &#34;legendFormat&#34;: &#34;User CPU % - {{instance}}&#34;
          }
        ]
      }
    ],
    &#34;time&#34;: {
      &#34;from&#34;: &#34;now-6h&#34;,
      &#34;to&#34;: &#34;now&#34;
    }
  }
}

七、使用说明

7.1 快速开始

bash 复制代码
# 1. 克隆仓库
git clone https://github.com/your-repo/redis-cluster-docker.git
cd redis-cluster-docker

# 2. 配置环境变量
cp .env.example .env
# 编辑 .env 文件,设置密码和其他配置

# 3. 启动集群
chmod +x start-cluster.sh
./start-cluster.sh

# 4. 测试集群
chmod +x test-cluster.sh
./test-cluster.sh

# 5. 访问管理界面
# Redis Commander: http://localhost:8081
# 用户名: admin
# 密码: 你的REDIS_PASSWORD

7.2 常用命令

bash 复制代码
# 查看集群状态
docker exec redis-cluster-node-1 redis-cli -a &#34;你的密码&#34; cluster info

# 查看集群节点
docker exec redis-cluster-node-1 redis-cli -a &#34;你的密码&#34; cluster nodes

# 查看集群槽分配
docker exec redis-cluster-node-1 redis-cli -a &#34;你的密码&#34; cluster slots

# 重启集群
docker-compose restart

# 查看日志
docker-compose logs -f redis-node-1

# 进入容器
docker exec -it redis-cluster-node-1 sh

# 备份集群
docker-compose exec redis-cluster-node-1 redis-cli -a &#34;你的密码&#34; save

7.3 故障处理

bash 复制代码
# 1. 节点故障恢复
# 如果某个节点故障,重启该节点即可
docker-compose restart redis-node-1

# 2. 集群重新初始化
# 如果集群配置损坏,可以重新初始化
docker-compose down -v
./start-cluster.sh

# 3. 数据恢复
# 从备份恢复数据
tar -xzf backups/20240101_120000.tar.gz
cp -r backups/20240101_120000/data/node1/* ./data/node1/
# 重启集群

# 4. 性能调优
# 调整内存限制
# 在 .env 文件中设置 REDIS_MAXMEMORY=4gb
# 重启集群

八、安全和优化建议

8.1 安全配置

yaml 复制代码
# 安全配置最佳实践
security:
  # 1. 强密码策略
  requirepass: &#34;复杂密码@包含大小写数字特殊字符&#34;
  
  # 2. 禁用危险命令
  rename-command:
    FLUSHDB: &#34;&#34;
    FLUSHALL: &#34;&#34;
    CONFIG: &#34;&#34;
    KEYS: &#34;&#34;
    SHUTDOWN: &#34;&#34;
    
  # 3. 网络限制
  bind: 0.0.0.0  # 生产环境应绑定特定IP
  protected-mode: yes
  
  # 4. SSL/TLS 加密
  tls-port: 6380
  tls-cert-file: /path/to/redis.crt
  tls-key-file: /path/to/redis.key
  tls-ca-cert-file: /path/to/ca.crt
  
  # 5. 客户端限制
  maxclients: 10000
  timeout: 300
  
  # 6. 慢查询日志
  slowlog-log-slower-than: 10000
  slowlog-max-len: 128

8.2 性能优化

yaml 复制代码
# 性能优化配置
performance:
  # 1. 内存优化
  maxmemory: &#34;4gb&#34;
  maxmemory-policy: &#34;allkeys-lru&#34;
  maxmemory-samples: 5
  
  # 2. 持久化优化
  appendonly: yes
  appendfsync: everysec
  auto-aof-rewrite-percentage: 100
  auto-aof-rewrite-min-size: 64mb
  
  # 3. 网络优化
  tcp-keepalive: 300
  tcp-backlog: 511
  
  # 4. 集群优化
  cluster-node-timeout: 5000
  cluster-replica-validity-factor: 10
  
  # 5. 内核参数优化
  # 在宿主机上设置
  # echo never > /sys/kernel/mm/transparent_hugepage/enabled
  # sysctl -w net.core.somaxconn=65535
  # sysctl -w vm.overcommit_memory=1

这个 Redis 集群部署方案提供了完整的生产级解决方案,包含 Docker Compose 部署、Kubernetes 部署、监控告警、备份恢复等功能,可以直接用于生产环境。

相关推荐
星辰徐哥4 小时前
Spring Boot 微服务架构设计与实现
spring boot·后端·微服务
星辰徐哥4 小时前
Spring Boot 数据导入导出与报表生成
spring boot·后端·ui
明夜之约4 小时前
Spring Boot 自动装配源码
java·spring boot·后端
Leaton Lee4 小时前
Spring Boot分层架构详解:从Controller到Service再到Mapper的完整流程
java·spring boot·后端·架构
Micro麦可乐4 小时前
Spring Boot 实战:从零设计一个短链系统(含完整代码与数据库设计)
数据库·spring boot·后端·哈希算法·雪花算法·短链系统
Jinkxs4 小时前
Resilience4j- 与 Spring Boot 快速集成:自动配置与基础注解使用
java·spring boot·后端
毕设源码_郑学姐4 小时前
计算机毕业设计springboot网络相册设计与实现 基于Spring Boot框架的在线相册管理系统开发与应用 Spring Boot驱动的网络影集设计与实践
spring boot·后端·课程设计
辣机小司4 小时前
【踩坑记录:Spring Boot 配置文件读取值不一致?警惕 YAML 的“八进制陷阱”与 SnakeYAML 版本之谜】
java·spring boot·后端·yaml·踩坑记录
码农阿豪4 小时前
从零到一:Spring Boot快速接入金仓数据库实战
数据库·spring boot·后端
追逐时光者4 小时前
一个基于 .NET 与 Avalonia 构建、面向 TrinityCore 的开源 WoW 数据库编辑器
后端·.net