2. 环境搭建与集群部署:单机/哨兵/集群模式配置、Docker Compose 编排、常见启动坑

2.1 方案概述

Redis 部署模式分为三种:单机(Standalone)、哨兵(Sentinel)、集群(Cluster)。生产环境落地时,选型与配置直接决定后续运维复杂度与容灾能力。下面从原理、配置要点、Docker Compose 编排到常见踩坑点逐层拆解。

核心对比表:三种模式适用场景
模式 数据分片 自动故障转移 读写分离 推荐场景
单机 无 无 不可 开发测试、缓存量小、可容忍停机
哨兵 无 支持(选举新 master) 通过 sentinel 通知客户端 核心业务单主多从,高可用但数据量不超单机
集群 16384 个槽位 自动(gossip 协议) 原生支持 slave 读 海量数据(TB 级)、高吞吐、需水平扩展

2.2 单机模式配置与启动坑

单机配置核心是禁用保护模式、设置密码、持久化策略。最小化 redis.conf 示例如下:

# redis.conf – 单机生产建议
bind 0.0.0.0
port 6379
requirepass myStrongP@ss
masterauth myStrongP@ss
daemonize no
logfile /var/log/redis/redis.log
dir /data
dbfilename dump.rdb
appendonly yes
appendfsync everysec
save 900 1
save 300 10
save 60 10000
maxmemory 2gb
maxmemory-policy allkeys-lru
常见启动坑 #1:保护模式 – 不显式设置 bind 0.0.0.0 或 requirepass 时,Redis 默认开启保护模式,仅允许本地回环地址连接,远程工具(如 RedisInsight)无法访问。
常见启动坑 #2:持久化权限 – 容器化运行时 /data 目录必须可写;日志文件所在目录必须存在,否则 Redis 启动后立即退出。使用 Docker 时需挂载卷并确保 uid 一致。

2.3 哨兵模式配置与部署

哨兵至少需要 3 个实例(奇数)形成 quorum。三节点拓扑:1 master + 2 slave + 3 sentinel。各 sentinel 配置模板:

# sentinel.conf – 三个节点几乎一致,仅 port 和 monitor 的 IP 不同
port 26379
daemonize no
sentinel monitor mymaster 10.0.0.10 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel auth-pass mymaster myStrongP@ss
protected-mode no
logfile /var/log/redis/sentinel.log

mymaster 为逻辑名称,所有 sentinel 必须一致;quorum=2 表示至少两个 sentinel 同意才触发故障转移。

生产经验: sentinel 本身不持久化数据,但必须独立部署(不要与 Redis 实例共用容器),否则宕机时同时丢失哨兵与数据节点。

2.4 集群模式配置要点

集群最少 6 个节点(3 master + 3 slave),每个 master 分配 5461~5462 个哈希槽。关键配置项:

# redis-cluster.conf – 每个节点独立,仅端口不同
port 7000
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
appendonly yes
appendfsync everysec
requirepass myStrongP@ss
masterauth myStrongP@ss

启动后需要手动创建集群(使用 redis-cli --cluster create 或 Docker 网络自动发现)。槽位分配失败、节点间无法互访是最常见的两个坑。

2.5 使用 Docker Compose 编排集群

以哨兵模式为例:编排文件分为 redis-master、redis-slave、sentinel 三个 service。注意网络模式选用自定义 bridge 以便主机名解析。

version: '3.8'
services:
  redis-master:
    image: redis:7-alpine
    container_name: redis-master
    command: redis-server /etc/redis/redis.conf
    volumes:
      - ./conf/master.conf:/etc/redis/redis.conf
      - ./data/master:/data
    networks:
      - cache-net
    ports:
      - "6379:6379"

  redis-slave-1:
    image: redis:7-alpine
    container_name: redis-slave-1
    command: redis-server /etc/redis/redis.conf --slaveof redis-master 6379
    volumes:
      - ./conf/slave.conf:/etc/redis/redis.conf
      - ./data/slave1:/data
    networks:
      - cache-net
    ports:
      - "6380:6379"
    depends_on:
      - redis-master

  redis-slave-2:
    image: redis:7-alpine
    container_name: redis-slave-2
    command: redis-server /etc/redis/redis.conf --slaveof redis-master 6379
    volumes:
      - ./conf/slave.conf:/etc/redis/redis.conf
      - ./data/slave2:/data
    networks:
      - cache-net
    ports:
      - "6381:6379"
    depends_on:
      - redis-master

  sentinel-1:
    image: redis:7-alpine
    container_name: sentinel-1
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./conf/sentinel-1.conf:/etc/redis/sentinel.conf
    networks:
      - cache-net
    ports:
      - "26379:26379"
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2

  sentinel-2:
    image: redis:7-alpine
    container_name: sentinel-2
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./conf/sentinel-2.conf:/etc/redis/sentinel.conf
    networks:
      - cache-net
    ports:
      - "26380:26379"
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2

  sentinel-3:
    image: redis:7-alpine
    container_name: sentinel-3
    command: redis-sentinel /etc/redis/sentinel.conf
    volumes:
      - ./conf/sentinel-3.conf:/etc/redis/sentinel.conf
    networks:
      - cache-net
    ports:
      - "26381:26379"
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2

networks:
  cache-net:
    driver: bridge

2.6 常见启动坑与排查清单

  1. 端口冲突 / 映射覆盖 – 本地已占用 6379 导致容器无法启动;使用 docker ps -a 查看已停止容器同样占用端口。
  2. 配置文件语法错误 – 如 requirepass 与 masterauth 不匹配,slave 复制中断;集群模式下 cluster-enabled yes 拼写错误导致 Redis 回退为单机模式。
  3. 网络连通性 – 默认 bridge 网络内容器通过容器名通信;若使用自定义网络需确保所有 service 在相同 network 下。
  4. 持久化数据冲突 – 多实例挂载同一 /data 目录导致 AOF/RDB 文件互相覆盖;必须为每个容器分配独立宿主机目录。
  5. 内存限制与 OOM – 未设置 maxmemory 时容器内内存不足被内核 kill;生产建议配合 --memory 资源限制与 swap 禁用。

2.7 部署流程示意图(哨兵模式)

下图展示哨兵模式下 master 选举与故障转移的核心流程:

哨兵模式故障转移流程 Master (主节点) Slave-1 Slave-2 Sentinel 集群 (3 节点) 监控 + 选举 → quorum=2 Master 宕机 新 Master (原 Slave-1) 新 Slave (原 Slave-2 切换) 关键说明 1. Sentinel 通过 PING 检测 Master 是否存活。 2. 当 quorum=2 个 Sentinel 同时认为 Master 下线时触发 failover。 3. 选举新 Master(优先从 slave 中选 repl_offset 最新的一个)。 4. 其余 slave 自动切换为新 Master 的从节点。

2.8 集群模式编排补充

集群模式的 Docker Compose 编排与哨兵类似,但需额外处理:

  • 各节点使用 cluster-announce-ip 与 cluster-announce-port 固定自身 IP/端口,避免 Docker 内部 IP 变化导致槽位漂移。
  • 初始化集群命令示例(在任意 master 节点容器内执行):
redis-cli --cluster create \
  10.0.0.10:7000 10.0.0.11:7001 10.0.0.12:7002 \
  10.0.0.13:7003 10.0.0.14:7004 10.0.0.15:7005 \
  --cluster-replicas 1 \
  -a myStrongP@ss
集群启动坑 #3:节点间时序 – 所有节点必须全部启动并加入网络后再执行 create 命令;否则部分节点未就绪会导致槽位分配失败。使用 depends_on 不能完全保证服务就绪(Redis 进程启动后仍需短暂初始化),建议在编排中加入 healthcheck 或手动 sleep 5 秒。
性能优化建议: 集群模式下尽量将同一业务的数据使用 hash tag 存入同一槽位,避免跨节点事务与批量操作。依据业务 key 特性设计 tag 规则,减少 MOVED 重定向开销。

2.9 多环境配置管理

不同环境(开发、测试、生产)的配置差异建议使用环境变量覆盖:

# docker-compose.yml 片段
services:
  redis-master:
    environment:
      - REDIS_PASSWORD=${REDIS_PASSWORD:-defaultPass}
      - REDIS_MAXMEMORY=2gb
    command: >
      redis-server --requirepass ${REDIS_PASSWORD}
                   --masterauth ${REDIS_PASSWORD}
                   --maxmemory 2gb
                   --appendonly yes

避免将明文密码硬编码在 docker-compose 文件中,使用 .env 文件或 CI/CD 环境变量注入。

2.10 本章小结

  • 单机模式配置最简,但需显式关闭保护模式、设置密码与持久化。
  • 哨兵模式依赖奇数个 sentinel 节点,quorum 取值为 N/2+1。
  • 集群模式最少 6 节点,初始化必须所有节点就绪后再创建槽位。
  • Docker Compose 编排时统一使用自定义 bridge 网络、独立持久化目录、健康检查。
  • 常见启动坑集中在端口冲突、配置语法、网络连通性、文件权限和内存失控。