如何搭建redis集群

概述
本文将介绍搭建redis集群的详细步骤,从两个维度:第一是从集群的形式的维度介绍:主从集群、哨兵集群以及分片集群如何搭建。第二个维度是从指令的角度:分别介绍如何使用docker指令和linux原生指令搭建。

正文
以下是Redis集群搭建的详细教程,从主从复制、哨兵(Sentinel)、分片(Redis Cluster) 三个模式,以及Linux原生、Docker两种实现方式展开,涵盖环境准备、配置、启动、验证全流程。

一、主从复制集群(读写分离+数据备份)

主从复制是最基础的集群模式:1个主节点(写操作)+ N个从节点(读操作),从节点通过复制主节点数据实现备份。

1. Linux原生搭建(单机多实例示例,3节点:1主2从)

环境准备
  • 服务器:1台Linux(以CentOS 7为例),已安装Redis(建议6.x+,安装方式:yum install redis 或源码编译)。
  • 端口规划:主节点6379,从节点6380、6381。
步骤1:配置主节点(6379)
  1. 复制默认配置文件(避免修改原文件):

    mkdir -p /etc/redis/cluster/master-slave
    cp /etc/redis.conf /etc/redis/cluster/master-slave/redis-6379.conf
    
  2. 编辑主节点配置(redis-6379.conf):

    port 6379                  # 主节点端口
    bind 0.0.0.0               # 允许所有IP访问(生产环境需指定具体IP)
    protected-mode no          # 关闭保护模式(允许远程连接)
    daemonize yes              # 后台运行
    pidfile /var/run/redis-6379.pid  # PID文件路径
    logfile /var/log/redis-6379.log  # 日志文件路径
    dir /var/lib/redis/6379    # 数据目录(需提前创建:mkdir -p /var/lib/redis/6379)
    
  3. 启动主节点:

    redis-server /etc/redis/cluster/master-slave/redis-6379.conf
    
步骤2:配置从节点(6380、6381)
  1. 复制主节点配置,修改为从节点参数(以6380为例):

    cp /etc/redis/cluster/master-slave/redis-6379.conf /etc/redis/cluster/master-slave/redis-6380.conf
    
  2. 编辑从节点配置(redis-6380.conf):

    port 6380                  # 从节点端口(6381同理)
    pidfile /var/run/redis-6380.pid
    logfile /var/log/redis-6380.log
    dir /var/lib/redis/6380    # 数据目录(mkdir -p /var/lib/redis/6380)
    replicaof 127.0.0.1 6379   # 关键:指定主节点IP和端口(多机部署替换为实际主节点IP)
    replica-read-only yes      # 从节点只读(默认开启,建议保持)
    
  3. 同理配置6381节点(端口、文件路径、replicaof 均指向主节点6379)。

  4. 启动从节点:

    redis-server /etc/redis/cluster/master-slave/redis-6380.conf
    redis-server /etc/redis/cluster/master-slave/redis-6381.conf
    
步骤3:验证主从状态
  1. 查看主节点信息:

    redis-cli -p 6379 info replication
    

    输出应包含:

    role:master
    connected_slaves:2  # 2个从节点连接
    slave0:ip=127.0.0.1,port=6380,state=online,...
    slave1:ip=127.0.0.1,port=6381,state=online,...
    
  2. 查看从节点信息(以6380为例):

    redis-cli -p 6380 info replication
    

    输出应包含:

    role:slave
    master_host:127.0.0.1
    master_port:6379
    master_link_status:up  # 主从连接正常
    
  3. 数据同步验证:

    • 主节点写入数据:redis-cli -p 6379 set test 123
    • 从节点读取数据:redis-cli -p 6380 get test 应返回 123
注意事项
  • 生产环境需设置密码:主节点配置 requirepass 密码,从节点配置 masterauth 密码(与主节点一致)。
  • 多机部署时,replicaof 需指定主节点的实际IP(非127.0.0.1),并开放防火墙端口(firewall-cmd --add-port=6379/tcp --permanent && firewall-cmd --reload)。

2. Docker搭建(1主2从)

环境准备
  • 安装Docker:yum install docker -y && systemctl start docker && systemctl enable docker。
  • 拉取Redis镜像:docker pull redis:6.2。
步骤1、启动多个Redis实例

使用docker-compose文件构建主从集群,将docker-compose文件放在linux系统中/root/redis目录中
文件内容如下:

version: "3.2"

services:
  r1:
    image: redis
    container_name: r1
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7001"]
  r2:
    image: redis
    container_name: r2
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7002"]
  r3:
    image: redis
    container_name: r3
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7003"]

上述文件起到的作用是:
用于定义和管理多个 Docker 容器的运行。具体来说,它的作用是启动 3 个 Redis 容器,并配置它们在主机的不同端口运行,具体内容解释如下:

1. 版本声明(version: "3.2")

指定当前 Docker Compose 配置文件遵循的语法版本为 3.2(不同版本支持的特性略有差异,3.2 是较常用的稳定版本)。

2. 服务定义(services 部分)

services 下定义了 3 个服务(r1、r2、r3),每个服务对应一个 Redis 容器,配置项含义如下:

  • image: redis:指定容器基于官方的 redis 镜像运行(会自动从 Docker Hub 拉取最新版 Redis 镜像)。
  • container_name: r1(r2/r3):指定容器的名称,分别为 r1、r2、r3(方便识别和管理)。
  • network_mode: "host":容器使用主机网络模式(即容器不分配独立的网络地址,直接共享主机的网络栈)。这意味着容器内的端口会直接映射到主机的相同端口(无需额外配置 ports 映射)。
  • entrypoint: ["redis-server", "--port", "7001"](7002/7003):覆盖 Redis 容器默认的启动命令,指定启动时绑定的端口:
    • r1 容器的 Redis 服务运行在主机的 7001 端口;
    • r2 容器的 Redis 服务运行在主机的 7002 端口;
    • r3 容器的 Redis 服务运行在主机的 7003 端口。

文件创建完成并放到指定位置后,执行命令,运行集群:

# 新版本执行该指令
docker compose up -d 
# 老版本执行该指令
docker-compose up -d 

执行命令

docker ps

可以发现都正常启动了

步骤2:建立集群

虽然我们启动了3个Redis实例,但是它们并没有形成主从关系。我们需要通过命令来配置主从关系。
有临时和永久两种模式:

  • 永久生效:在redis.conf文件中利用slaveof命令指定master节点

  • 临时生效:直接利用redis-cli控制台输入slaveof命令,指定master节点

我们测试临时模式,首先连接r2,让其以r1为master

# 进入r2中
docker exec -it r2 redis-cli -p 7002
# 让r2作为r1(7001)的从节点,下面的ip写主节点所在的主机的ip
slaveof 192.168.150.101 7001

r3的操作与上述r2的操作一致
操作完成之后可以进入r1看一下集群的状态

# 连接r1
docker exec -it r1 redis-cli -p 7001
# 查看集群状态
info replication

结果会返回类似与下述内容的文本:

127.0.0.1:7001> info replication
# Replication
role:master # 这个是当前进入的节点的身份,master即为主节点
connected_slaves:2 # 这个是在说当前主节点有两个从节点
slave0:ip=192.168.150.101,port=7002,state=online,offset=140,lag=1
slave1:ip=192.168.150.101,port=7003,state=online,offset=140,lag=1
master_failover_state:no-failover
master_replid:16d90568498908b322178ca12078114e6c518b86
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:140
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:140
步骤3:测试

可以分别在三个节点上执行set、get命令,会发现只有r1上可以执行set命令。
说明当前集群的读写操作已经分离了。

二、哨兵(Sentinel)集群(主从高可用)

哨兵用于监控主从集群,当主节点故障时自动将从节点升级为新主节点,实现高可用。通常需3个哨兵节点(避免单点故障)。

1. Linux原生搭建(基于主从集群:1主2从+3哨兵)

环境准备
  • 已完成「主从复制集群(Linux原生)」搭建(主6379,从6380、6381)。
  • 哨兵端口规划:26379、26380、26381。
步骤1:配置哨兵节点
  1. 创建哨兵配置文件目录:

    mkdir -p /etc/redis/cluster/sentinel
    
  2. 编写哨兵配置(以26379为例,sentinel-26379.conf):

    port 26379                  # 哨兵端口
    bind 0.0.0.0                # 允许所有IP访问
    protected-mode no           # 关闭保护模式
    daemonize yes               # 后台运行
    pidfile /var/run/redis-sentinel-26379.pid
    logfile /var/log/redis-sentinel-26379.log
    dir /tmp                    # 工作目录
    # 监控主节点:名称(自定义)、主节点IP:端口、quorum(至少多少哨兵认为主节点故障才触发切换,3哨兵建议设2)
    sentinel monitor mymaster 127.0.0.1 6379 2
    # 主节点无响应30秒后标记为下线
    sentinel down-after-milliseconds mymaster 30000
    # 故障转移时最多1个从节点同时同步新主节点
    sentinel parallel-syncs mymaster 1
    # 故障转移超时时间(180秒)
    sentinel failover-timeout mymaster 180000
    # 若主节点有密码,需添加:sentinel auth-pass mymaster 密码
    
  3. 复制配置文件到26380、26381节点,修改端口、PID/日志路径(如port 26380)。

步骤2:启动哨兵节点
redis-sentinel /etc/redis/cluster/sentinel/sentinel-26379.conf
redis-sentinel /etc/redis/cluster/sentinel/sentinel-26380.conf
redis-sentinel /etc/redis/cluster/sentinel/sentinel-26381.conf
步骤3:验证哨兵功能
  1. 查看哨兵状态(以26379为例):

    redis-cli -p 26379 info sentinel
    

    输出应包含:

    sentinel_masters:1
    sentinel_monitored_slaves:2  # 监控的从节点数
    sentinel_leader:xxx  # 哨兵集群的leader(负责故障转移)
    
  2. 模拟主节点故障并验证自动切换:

    • 停止主节点:redis-cli -p 6379 shutdown
    • 查看哨兵日志(tail -f /var/log/redis-sentinel-26379.log),应显示“故障转移开始”“新主节点选举”等信息。
    • 查看原从节点(如6380)状态:redis-cli -p 6380 info replication,role 应变为 master。
    • 重启原主节点(6379):redis-server /etc/redis/cluster/master-slave/redis-6379.conf,此时它会自动成为新主节点的从节点。

2. Docker搭建(1主2从+3哨兵)

环境准备
  • 需要先完成上文通过docker搭建主从模式的集群
    首先,我们停掉之前的redis集群:
# 老版本DockerCompose
docker-compose down

# 新版本Docker
docker compose down
步骤1:创建哨兵配置文件

创建sentinel.conf模板

# ip需要设置为linux系统所在的主机ip
sentinel announce-ip "192.168.150.101"
sentinel monitor hmaster 192.168.150.101 7001 2
sentinel down-after-milliseconds hmaster 5000
sentinel failover-timeout hmaster 60000

sentinel.conf文件内容的含义是:

  • sentinel announce-ip "192.168.150.101":声明当前sentinel的ip
  • sentinel monitor hmaster 192.168.150.101 7001 2:指定集群的主节点信息
    • hmaster:主节点名称,自定义,任意写
    • 192.168.150.101 7001:主节点的ip和端口
    • 2:认定master下线时的quorum值
  • sentinel down-after-milliseconds hmaster 5000:声明master节点超时多久后被标记下线
  • sentinel failover-timeout hmaster 60000:在第一次故障转移失败后多久再次重试

在Redis Sentinel(哨兵)机制中,quorum值是用于判断主节点是否“客观下线(ODown)”的最小哨兵节点投票数,是保障故障检测可靠性的关键机制,具体含义如下:

  • 作用:当哨兵集群监测主节点时,需要至少quorum个哨兵节点都认为该主节点“主观下线(SDown,单个哨兵的判断)”,才会将其标记为“客观下线(ODown,集群层面的判断)”,进而触发故障转移流程。
  • 意义:避免单个哨兵的“误判”,通过多节点投票机制确保故障检测的准确性。例如配置中quorum=2,意味着至少2个哨兵节点都判定主节点不可达,才会认定主节点真的下线。

补充:故障转移的执行还需要满足“大多数哨兵节点同意”(即超过半数),因此quorum通常建议设置为哨兵节点总数的一半以上(比如3个哨兵时,quorum设为2;5个哨兵时,quorum设为3),以同时满足“故障检测阈值”和“故障转移的多数同意”。

在虚拟机的/root/redis目录下新建3个文件夹:s1、s2、s3:
image

将准备好的sentinel.conf文件拷贝到三个文件夹中
修改docker-compose.yaml文件

内容如下:

version: "3.2"

services:
  r1:
    image: redis
    container_name: r1
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7001"]
  r2:
    image: redis
    container_name: r2
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7002", "--slaveof", "192.168.150.101", "7001"]
  r3:
    image: redis
    container_name: r3
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7003", "--slaveof", "192.168.150.101", "7001"]
  s1:
    image: redis
    container_name: s1
    volumes:
      - /root/redis/s1:/etc/redis
    network_mode: "host"
    entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27001"]
  s2:
    image: redis
    container_name: s2
    volumes:
      - /root/redis/s2:/etc/redis
    network_mode: "host"
    entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27002"]
  s3:
    image: redis
    container_name: s3
    volumes:
      - /root/redis/s3:/etc/redis
    network_mode: "host"
    entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27003"]
步骤2:运行

直接运行命令,启动集群:

# 新
docker compose up -d
# 老
docker-compose up -d

我们以s1节点为例,查看其运行日志:

# Sentinel ID is 8e91bd24ea8e5eb2aee38f1cf796dcb26bb88acf
# +monitor master hmaster 192.168.150.101 7001 quorum 2
* +slave slave 192.168.150.101:7003 192.168.150.101 7003 @ hmaster 192.168.150.101 7001
* +sentinel sentinel 5bafeb97fc16a82b431c339f67b015a51dad5e4f 192.168.150.101 27002 @ hmaster 192.168.150.101 7001
* +sentinel sentinel 56546568a2f7977da36abd3d2d7324c6c3f06b8d 192.168.150.101 27003 @ hmaster 192.168.150.101 7001
* +slave slave 192.168.150.101:7002 192.168.150.101 7002 @ hmaster 192.168.150.101 7001

可以看到sentinel已经联系到了7001这个节点,并且与其它几个哨兵也建立了链接。哨兵信息如下:

  • 27001:Sentinel ID是8e91bd24ea8e5eb2aee38f1cf796dcb26bb88acf
  • 27002:Sentinel ID是5bafeb97fc16a82b431c339f67b015a51dad5e4f
  • 27003:Sentinel ID是56546568a2f7977da36abd3d2d7324c6c3f06b8d
步骤3:测试

我们连接7001这个master节点,然后通过命令让其休眠60秒,模拟宕机:

  # 连接7001这个master节点,通过sleep模拟服务宕机,60秒后自动恢复
  docker exec -it r1 redis-cli -p 7001 DEBUG sleep 60
  1. 模拟主节点故障:
    • 停止主容器:docker stop redis-master
    • 查看哨兵日志:docker logs -f sentinel1,观察故障转移过程。
    • 查看新主节点:docker exec -it redis-slave1 redis-cli info replication,role 应为 master。
      稍微等待一段时间后,会发现sentinel节点触发了failover。
步骤4:如果需要用RedisTemplate连接哨兵集群

分为三步:

  • 1)引入依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  • 2)配置哨兵地址
spring:
  redis:
    sentinel:
      master: hmaster # 集群名
      nodes: # 哨兵地址列表
        - 192.168.150.101:27001
        - 192.168.150.101:27002
        - 192.168.150.101:27003
  • 3)配置读写分离
@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
    return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}

三、分片(Redis Cluster)集群(数据分片+高可用)

分片集群将数据分散到多个主节点(每个主节点负责一部分哈希槽),同时每个主节点有1个从节点备份,支持横向扩展(最多16384个槽)。通常需3主3从(最小高可用配置)。

1. Linux原生搭建(3主3从,端口7000-7005)

环境准备
  • 1台Linux服务器(或6台,此处用单机多实例),已安装Redis。
  • 端口规划:主节点7000、7001、7002;从节点7003、7004、7005(总线端口=端口+10000,用于节点通信,如17000-17005)。
步骤1:配置所有节点
  1. 创建节点配置目录:

    mkdir -p /etc/redis/cluster/shard/{7000,7001,7002,7003,7004,7005}
    
  2. 编写节点配置(以7000为例,/etc/redis/cluster/shard/7000/redis.conf):

    port 7000                  # 节点端口
    bind 0.0.0.0               # 允许所有IP访问
    protected-mode no          # 关闭保护模式
    daemonize yes              # 后台运行
    pidfile /var/run/redis-7000.pid
    logfile /var/log/redis-7000.log
    dir /var/lib/redis/7000    # 数据目录(mkdir -p /var/lib/redis/7000)
    cluster-enabled yes        # 开启集群模式
    cluster-config-file nodes-7000.conf  # 集群配置文件(自动生成)
    cluster-node-timeout 15000 # 节点超时时间(15秒)
    appendonly yes             # 开启AOF持久化
    
  3. 复制配置文件到7001-7005,修改端口、PID/日志/数据目录(如port 7001,dir /var/lib/redis/7001)。

步骤2:启动所有节点
redis-server /etc/redis/cluster/shard/7000/redis.conf
redis-server /etc/redis/cluster/shard/7001/redis.conf
redis-server /etc/redis/cluster/shard/7002/redis.conf
redis-server /etc/redis/cluster/shard/7003/redis.conf
redis-server /etc/redis/cluster/shard/7004/redis.conf
redis-server /etc/redis/cluster/shard/7005/redis.conf
步骤3:创建集群并分配槽位

使用redis-cli --cluster命令初始化集群:

redis-cli --cluster create \
  127.0.0.1:7000 \
  127.0.0.1:7001 \
  127.0.0.1:7002 \
  127.0.0.1:7003 \
  127.0.0.1:7004 \
  127.0.0.1:7005 \
  --cluster-replicas 1  # 每个主节点分配1个从节点
  • 执行后会提示“是否接受槽位分配方案”,输入yes确认。
步骤4:验证集群状态
  1. 查看集群信息(连接任意节点):

    redis-cli -c -p 7000 cluster info  # -c:启用集群模式(自动跳转节点)
    

    输出应包含 cluster_state:ok(集群正常)。

  2. 查看节点角色与槽位分配:

    redis-cli -c -p 7000 cluster nodes
    

    输出中,master 节点会显示负责的槽位(如0-5460),slave 节点会显示对应的主节点ID。

  3. 数据分片验证:

    • 写入数据:redis-cli -c -p 7000 set key1 123,会自动跳转到负责key1槽位的主节点。
    • 查看槽位:redis-cli -c -p 7000 cluster keyslot key1(返回槽位编号,如9189)。
    • 从节点验证:连接从节点(如7003),get key1 可读取数据(主节点同步给从节点)。
  4. 故障转移验证:

    • 停止主节点7000:redis-cli -p 7000 shutdown
    • 查看集群状态:redis-cli -c -p 7001 cluster nodes,原7000的从节点(如7003)会升级为新主节点。

2. Docker搭建(3主3从,端口7000-7005)

环境准备
  • 已安装Docker,拉取Redis镜像(docker pull redis:6.2)。
步骤1:配置文件

在虚拟机的/root目录下新建一个redis-cluster目录,然后在其中新建一个docker-compose.yaml文件,内容如下:

version: "3.2"

services:
  r1:
    image: redis
    container_name: r1
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7001", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
  r2:
    image: redis
    container_name: r2
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7002", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
  r3:
    image: redis
    container_name: r3
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7003", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
  r4:
    image: redis
    container_name: r4
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7004", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
  r5:
    image: redis
    container_name: r5
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7005", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
  r6:
    image: redis
    container_name: r6
    network_mode: "host"
    entrypoint: ["redis-server", "--port", "7006", "--cluster-enabled", "yes", "--cluster-config-file", "node.conf"]
步骤2:启动集群

进入/root/redis-cluster目录,使用命令启动redis:

  docker-compose up -d

接下来,我们使用命令创建集群:

# 进入任意节点容器
docker exec -it r1 bash
# 然后,执行命令
redis-cli --cluster create --cluster-replicas 1 \
192.168.150.101:7001 192.168.150.101:7002 192.168.150.101:7003 \
192.168.150.101:7004 192.168.150.101:7005 192.168.150.101:7006

入yes然后回车。会发现集群开始创建
接着,我们可以通过命令查看集群状态:

redis-cli -p 7001 cluster nodes
步骤3:验证集群状态

我们来测试一下,先于7001建立连接:

# 进入容器
docker exec -it r1 bash
# 进入redis-cli
redis-cli -c -p 7001
# 测试
set user jack

现在,我们添加一个新的key,这次加上{}:

# 试一下key中带{}
set user:{age} 21

# 再试一下key中不带{}
set age 20

分片集群的节点之间会互相通过ping的方式做心跳检测,超时未回应的节点会被标记为下线状态。当发现master下线时,会将这个master的某个slave提升为master。

我们先打开一个控制台窗口,利用命令监测集群状态:

watch docker exec -it r1 redis-cli -p 7001 cluster nodes

命令前面的watch可以每隔一段时间刷新执行结果,方便我们实时监控集群状态变化。

接着,我们故技重施,利用命令让某个master节点休眠。比如这里我们让7002节点休眠,打开一个新的ssh控制台,输入下面命令:

docker exec -it r2 redis-cli -p 7002 DEBUG sleep 30

过了一段时间之后7002的slave7006成为了master,等到7002恢复之后,他会作为7006的slave继续工作。

步骤4:如果需要用java客户端连接分片集群的步骤

RedisTemplate底层同样基于lettuce实现了分片集群的支持,而使用的步骤与哨兵模式基本一致:
1)引入redis的starter依赖

2)配置分片集群地址

spring:
  redis:
    cluster:
      nodes:
        - 192.168.150.101:7001
        - 192.168.150.101:7002
        - 192.168.150.101:7003
        - 192.168.150.101:8001
        - 192.168.150.101:8002
        - 192.168.150.101:8003

只有这部分的配置与哨兵模式略有差异
3)配置读写分离

总结

模式 核心作用 适用场景 实现复杂度
主从复制 读写分离、数据备份 读多写少,需简单备份 低
哨兵 主从高可用(自动故障转移) 需避免主节点单点故障 中
分片集群 数据分片、横向扩展 数据量大(超单节点容量) 高

根据业务需求选择模式:小流量用主从+哨兵;大流量/大数据量用分片集群。生产环境需注意密码、防火墙、持久化配置,确保安全性和数据可靠性。

posted @ 2025-11-12 16:27  谁来着?  阅读(125)  评论(0)    收藏  举报