前言:Redis 主从复制 + 哨兵模式是企业级开发中最常用的高可用方案,能实现自动故障转移,避免单点故障导致服务不可用。本文将从 Docker Compose 安装开始,一步步搭建 Redis 1 主 2 从 3 哨兵集群,全程实操,包含所有报错解决方案,新手也能轻松上手(实测可直接投产测试环境)。

环境说明:

  • 服务器:CentOS 7(云服务器 / 虚拟机均可,本文用虚拟机演示,IP:192.168.126.140)
  • Docker:已安装(若未安装,文中附带简易安装步骤)
  • Redis 版本:7.0.4(主从)、latest(哨兵,兼容 7.0+)
  • Docker Compose 版本:v2.20.2(稳定版)

核心目标:搭建 1 主 2 从 3 哨兵集群,实现主节点故障后,哨兵自动投票选举新主节点,保证 Redis 高可用。

一、前置准备:安装 Docker(已安装可跳过)

若服务器未安装 Docker,执行以下命令快速安装(一键复制,避免输错):

# 卸载旧版本(若有)
yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine

# 安装依赖
yum install -y yum-utils device-mapper-persistent-data lvm2

# 设置 Docker 镜像源(阿里云,加速下载)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 安装 Docker CE
yum install -y docker-ce docker-ce-cli containerd.io

# 启动 Docker 并设置开机自启
systemctl start docker
systemctl enable docker

# 验证 Docker 是否安装成功
docker --version

出现类似 Docker version 24.0.7, build afdd53b 提示,说明 Docker 安装成功。

二、安装 Docker Compose(重点步骤)

Docker Compose 用于一键管理多容器应用,是搭建主从哨兵的核心工具,步骤如下:

2.1 下载 Docker Compose 二进制文件

# 下载最新稳定版(v2.20.2,可根据官网更新版本号)
curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

若下载缓慢,可替换为阿里云镜像:

curl -L "https://mirrors.aliyun.com/docker-toolbox/linux/compose/v2.20.2/docker-compose-Linux-x86_64" -o /usr/local/bin/docker-compose

2.2 赋予执行权限

chmod +x /usr/local/bin/docker-compose

2.3 验证安装

docker-compose --version

出现类似 docker-compose version v2.20.2 提示,说明 Docker Compose 安装成功。

⚠️ 避坑提示:若出现 “command not found: docker-compose”,执行 ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose 建立软链接即可。

三、搭建 Redis 主从集群(1 主 2 从)

采用 Docker Compose 管理主从容器,目录结构清晰,便于后期维护,步骤如下:

3.1 创建主从目录结构

先创建统一的工作目录,避免文件混乱(本文目录路径:/docker/docker-master-slave/redis):

# 创建多级目录
mkdir -p /docker/docker-master-slave/redis

# 进入目录(后续所有操作都在此目录下)
cd /docker/docker-master-slave/redis

3.2 编写 docker-compose.yml 文件

创建并编辑 docker-compose.yml,复制以下内容(注释详细,可直接复制):

version: '3.8'  # 版本兼容 Docker Compose v2+
services:
  # Redis 主节点
  redis-master:
    image: redis:7.0.4  # 主从用 7.0.4 稳定版
    container_name: redis-master  # 容器名,固定,便于哨兵识别
    ports:
      - "6379:6379"  # 主节点端口映射
    command: redis-server --requirepass 123456 --bind 0.0.0.0  # 密码123456,允许所有IP访问
    volumes:
      - ./master/data:/data  # 数据持久化目录
    networks:
      - redis-network  # 统一网络,主从+哨兵都在这个网络

  # Redis 从节点1
  redis-slave-1:
    image: redis:7.0.4
    container_name: redis-slave-1
    ports:
      - "6380:6379"  # 从节点1端口,避免和主节点冲突
    command: redis-server --requirepass 123456 --slaveof redis-master 6379 --masterauth 123456 --bind 0.0.0.0
    # 核心配置:--slaveof 主节点容器名 主节点端口;--masterauth 主节点密码
    volumes:
      - ./slave1/data:/data
    networks:
      - redis-network
    depends_on:
      - redis-master  # 依赖主节点,主节点启动后再启动从节点

  # Redis 从节点2
  redis-slave-2:
    image: redis:7.0.4
    container_name: redis-slave-2
    ports:
      - "6381:6379"  # 从节点2端口
    command: redis-server --requirepass 123456 --slaveof redis-master 6379 --masterauth 123456 --bind 0.0.0.0
    volumes:
      - ./slave2/data:/data
    networks:
      - redis-network
    depends_on:
      - redis-master

# 自定义网络,确保主从、哨兵能互相通信
networks:
  redis-network:
    driver: bridge

⚠️ 关键说明:

  • --bind 0.0.0.0:允许外部(包括容器内部)访问,避免哨兵连不上主从
  • 容器名固定为 redis-masterredis-slave-1redis-slave-2,后续哨兵配置会用到
  • 密码统一为 123456,可根据需求修改,但要保证主从、哨兵密码一致

3.3 启动主从集群

docker-compose.yml 所在目录(/docker/docker-master-slave/redis)执行:

docker-compose up -d

启动成功后,查看容器状态:

docker ps

若出现 3 个状态为 Up 的容器(redis-master、redis-slave-1、redis-slave-2),说明主从集群启动成功。

3.4 验证主从同步

进入主节点,写入数据,验证从节点是否能同步:

# 进入主节点容器
docker exec -it redis-master redis-cli -a 123456

# 写入测试数据
set test_key "redis-master-slave-test"

# 查看数据
get test_key

# 退出主节点
exit

进入任意一个从节点,查看是否能获取到主节点写入的数据:

# 进入从节点1
docker exec -it redis-slave-1 redis-cli -a 123456

# 查看主节点写入的数据(能获取到说明同步成功)
get test_key

# 尝试写入数据(从节点只读,会报错,正常现象)
set test_key2 "error"  # 报错:(error) READONLY You can't write against a read only replica.

# 退出从节点
exit

✅ 主从同步验证成功,主从集群搭建完成。

⚠️ 常见报错:若从节点无法同步,检查主节点 command 中是否加了 --bind 0.0.0.0,以及从节点 --masterauth 是否和主节点密码一致。

四、搭建 Redis 哨兵集群(3 个哨兵)

哨兵的核心作用是监控主从集群,当主节点故障时,自动选举新主节点,实现故障转移。步骤如下:

4.1 创建哨兵目录结构

在主从目录的同级目录下,创建哨兵目录(路径:/docker/docker-master-slave/sentinel):

# 进入上级目录
cd /docker/docker-master-slave

# 创建哨兵目录
mkdir -p sentinel

# 进入哨兵目录
cd sentinel

4.2 编写哨兵配置文件(3 个)

哨兵需要至少 3 个实例才能实现投票选举,创建 3 个哨兵配置文件(sentinel1.conf、sentinel2.conf、sentinel3.conf),内容完全一致,仅文件名不同。

# 创建并编辑第一个哨兵配置文件
vi sentinel1.conf

复制以下内容到配置文件中(保存退出:按 Esc,输入 :wq):

protected-mode no  # 关闭保护模式,允许外部访问
port 26379  # 哨兵端口(3个哨兵端口相同,容器内部不冲突)
sentinel monitor mymaster redis-master 6379 2  # 监控主节点(容器名redis-master,端口6379,2票同意即可故障转移)
sentinel down-after-milliseconds mymaster 5000  # 主节点5秒无响应,标记为下线
sentinel failover-timeout mymaster 60000  # 故障转移超时时间(60秒)
sentinel parallel-syncs mymaster 1  # 故障转移后,从节点同步新主节点的并发数
sentinel auth-pass mymaster 123456  # 主从节点的密码,和主从配置一致

复制上述配置文件,生成另外 2 个哨兵配置:

# 复制配置文件,生成sentinel2.conf和sentinel3.conf
cp sentinel1.conf sentinel2.conf
cp sentinel1.conf sentinel3.conf

⚠️ 避坑重点:sentinel monitor 后面的主节点必须写容器名 redis-master(不是 IP),因为主从和哨兵在同一个 Docker 网络,容器名可自动解析,避免 IP 变化导致哨兵连不上主节点。

4.3 编写哨兵 docker-compose.yml 文件

在哨兵目录(/docker/docker-master-slave/sentinel)下,创建 docker-compose.yml 文件:

version: '3.8'
services:
  # 哨兵1
  redis-sentinel-1:
    image: redis:latest  # 哨兵用latest版,兼容7.0+
    container_name: redis-sentinel-1
    ports:
      - "26379:26379"  # 哨兵1端口映射
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf  # 启动哨兵,指定配置文件
    volumes:
      - ./sentinel1.conf:/usr/local/etc/redis/sentinel.conf  # 挂载哨兵配置文件
    networks:
      - redis-network  # 和主从用同一个网络,确保能通信
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2  # 依赖主从节点,主从启动后再启动哨兵

  # 哨兵2
  redis-sentinel-2:
    image: redis:latest
    container_name: redis-sentinel-2
    ports:
      - "26380:26379"  # 哨兵2端口映射
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    volumes:
      - ./sentinel2.conf:/usr/local/etc/redis/sentinel.conf
    networks:
      - redis-network
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2

  # 哨兵3
  redis-sentinel-3:
    image: redis:latest
    container_name: redis-sentinel-3
    ports:
      - "26381:26379"  # 哨兵3端口映射
    command: redis-sentinel /usr/local/etc/redis/sentinel.conf
    volumes:
      - ./sentinel3.conf:/usr/local/etc/redis/sentinel.conf
    networks:
      - redis-network
    depends_on:
      - redis-master
      - redis-slave-1
      - redis-slave-2

# 关联主从的网络,确保哨兵能访问主从节点
networks:
  redis-network:
    external: true  # 引用外部网络(主从集群创建的网络)

⚠️ 关键说明:networksredis-network 设为 external: true,必须和主从集群的网络名称一致,否则哨兵无法和主从通信。

4.4 启动哨兵集群

在哨兵目录(/docker/docker-master-slave/sentinel)下执行:

docker-compose up -d

启动成功后,查看哨兵容器状态:

docker ps

若出现 3 个状态为 Up 的哨兵容器(redis-sentinel-1/2/3),说明哨兵集群启动成功。

4.5 验证哨兵监控状态

进入任意一个哨兵容器,查看监控的主节点状态:

# 进入哨兵1容器
docker exec -it redis-sentinel-1 redis-cli -p 26379

# 查看主节点状态(核心命令)
sentinel master mymaster

若输出中包含以下内容,说明哨兵监控正常:

status=ok
ip=172.19.0.2  # 主节点内部IP(无需关注,正常现象)
port=6379
slaves=2  # 2个从节点,和我们搭建的一致
sentinels=3  # 3个哨兵,和我们搭建的一致

✅ 哨兵集群搭建完成,已成功监控主从集群。

⚠️ 常见报错:若出现 flags: s_down,master,disconnected(主节点下线、连接失败),大概率是防火墙拦截,执行以下命令关闭防火墙(测试环境):

systemctl stop firewalld
systemctl disable firewalld

生产环境可开放 6379(Redis)和 26379(哨兵)端口,无需关闭防火墙:

firewall-cmd --add-port=6379/tcp --permanent
firewall-cmd --add-port=26379/tcp --permanent
firewall-cmd --reload

五、测试故障转移(核心验证)

故障转移是哨兵的核心功能,我们手动停止主节点,验证哨兵是否能自动选举新主节点:

5.1 停止主节点容器

# 停止主节点(redis-master)
docker stop redis-master

5.2 查看哨兵日志,观察故障转移过程

# 查看哨兵1日志(实时输出)
docker compose logs -f redis-sentinel-1

日志中会出现以下关键信息(说明故障转移成功):

# 主节点标记为下线
+sdown master mymaster 172.19.0.2 6379
# 投票选举新主节点
+vote-for-leader xxxxx 1
# 切换主节点(从节点升级为新主节点)
+switch-master mymaster 172.19.0.2 6379 172.19.0.3 6379

5.3 验证新主节点状态

# 进入哨兵容器,查看主节点状态
docker exec -it redis-sentinel-1 redis-cli -p 26379
sentinel master mymaster

若输出中出现以下内容,说明故障转移成功:

  • status=ok
  • address=172.19.0.3:6379(原从节点 1 的内部 IP,已升级为新主节点)
  • slaves=2(原主节点下线后,变为从节点,新主节点有 2 个从节点)

5.4 恢复原主节点(可选)

若想恢复原主节点,启动原主节点容器即可,哨兵会自动将其变为从节点,同步新主节点的数据:

docker start redis-master

再次查看主节点状态,会发现原主节点已变为从节点,新主节点仍为之前选举的从节点。

六、常见问题排查(避坑汇总)

本文汇总了实操中遇到的所有问题,新手可直接对照解决:

6.1 启动主从时,容器名冲突(Conflict. The container name "/redis-master" is already in use)

原因:之前启动过主从容器,未彻底删除,容器名被占用。解决方案:强制删除冲突容器,再重新启动:

docker rm -f redis-master redis-slave-1 redis-slave-2

6.2 哨兵连不上主节点(flags: s_down,master,disconnected)

原因:1. 防火墙拦截;2. 哨兵配置中主节点写的是 IP,不是容器名;3. 主从节点未加 --bind 0.0.0.0。解决方案:关闭防火墙(或开放端口),哨兵配置中主节点改为 redis-master,主从 command--bind 0.0.0.0

6.3 启动哨兵时,提示网络不存在(network redis-network not found)

原因:哨兵 docker-compose.yml 中引用的外部网络,主从集群未创建(或网络名称不一致)。解决方案:先启动主从集群,创建 redis-network 网络,再启动哨兵。

6.4 无法同时启动单机 Redis 和主从集群

原因:单机 Redis 和主从集群都用 6379 端口,端口冲突。解决方案:先停止其中一个,再启动另一个(停止主从用 docker compose down,停止单机用 docker stop redis)。

七、总结

本文从 Docker Compose 安装开始,一步步完成了 Redis 1 主 2 从 3 哨兵集群的搭建,包含主从同步验证、哨兵监控验证、故障转移测试,以及所有常见问题的解决方案。

核心要点:

  • 主从和哨兵必须在同一个 Docker 网络,哨兵配置主节点用容器名,避免 IP 变化导致通信失败。
  • 哨兵至少需要 3 个实例,才能实现投票选举,保证故障转移的可靠性。
  • 主从、哨兵密码必须一致,否则会出现认证失败,无法同步或监控。
  • 测试环境可关闭防火墙,生产环境建议开放对应端口,保证安全性。

更多推荐