Redis 主从复制 & 哨兵&集群模式笔记

一、主从复制

1. 常用命令

命令说明
info replication查看当前节点的主从模式(Master/Slave 角色,Slave 列表)
replicaof <ip> <port>将本节点设置为从节点,指定主节点的 ip 和 port(注意没有冒号 :

2. 示例

# 查看复制状态
info replication

# 将 127.0.0.1:6001 设置为主节点
replicaof 127.0.0.1 6001

返回 OK 表示成功。
此时:

  • 主节点写入:set a 100
  • 从节点读取:get a100

3. 配置文件方式(持久化)

redis.conf 中添加:

replicaof 127.0.0.1 6001

这样每次启动服务都会自动连上主节点。

4. 主从复制流程图

flowchart TD
    A[Master 节点] -->|写入数据| B[Slave 节点1]
    A -->|写入数据| C[Slave 节点2]
    B -->|只读| D[客户端]
    C -->|只读| D
    D -.->|写操作必须走 Master| A

二、哨兵模式 (Sentinel)

1. 哨兵是什么?

  • 哨兵(Sentinel)是一个独立的 Redis 进程
  • 功能:监控主节点健康状态,当主节点宕机时,自动将某个从节点提升为主节点,并通知客户端。

2. 配置步骤

  1. 配置监控对象

    sentinel monitor lbwnb 127.0.0.1 6001 1
    
    • lbwnb:哨兵名称(可自定义)
    • 127.0.0.1 6001:监控的主节点
    • 1:仲裁数量(至少多少个哨兵同意才执行故障转移)
  2. 复制 redis 文件夹,单独作为哨兵运行目录。

  3. 清空 redis.conf,只保留 sentinel 配置。

  4. 启动哨兵进程:

    redis-server.exe redis.windows.conf --sentinel
    

3. Java 程序接入

依赖

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>4.2.1</version>
</dependency>

Demo 代码

public static void main(String[] args) {
    // 定义哨兵地址集合
    Set<String> sentinels = new HashSet<>(Arrays.asList(
            "127.0.0.1:20001",
            "127.0.0.1:20002",
            "127.0.0.1:20003"
    ));

    // 通过哨兵池获取主节点连接
    try (JedisSentinelPool pool = new JedisSentinelPool("lbwnb", sentinels)) {
        Jedis jedis = pool.getResource();
        
        // 写入数据(会写到主节点)
        jedis.set("test", "114514");

        // 再次获取连接,验证数据读取
        Jedis jedis2 = pool.getResource();
        System.out.println(jedis2.get("test"));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

4. 哨兵模式工作流程图

sequenceDiagram
    participant S1 as Sentinel1
    participant S2 as Sentinel2
    participant S3 as Sentinel3
    participant M as Master
    participant R1 as Slave1
    participant R2 as Slave2
    participant C as Client

    C->>M: 写入数据
    M->>R1: 同步数据
    M->>R2: 同步数据
    
    Note over M: Master 宕机
    
    S1->>S2: 通知 Master 宕机
    S2->>S3: 通知 Master 宕机
    S3->>S1: 达成一致 (Quorum)
    
    S1->>R1: 提升为新 Master
    C->>R1: 继续写入数据 (自动切换)

三、集群模式

1. 插槽机制

  • Redis 集群包含 16384 个插槽

  • 每个节点维护部分插槽以及对应的键值对。

  • 插槽计算公式:

    slot = CRC16(key) % 16384
    
  • 举例:

    • 节点1负责 0-5460
    • 节点2负责 5461-10922
    • 节点3负责 10923-16383
    • key=a 哈希结果落到 666,就会分配到节点1。

2. 开启集群模式

  1. 复制 6 个 Redis 实例

  2. 在配置文件中开启:

    cluster-enabled yes
    
  3. 执行创建集群命令:

    redis-cli.exe --cluster create --cluster-replicas 1 \
    127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 \
    127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003
    
    • --cluster-replicas 1:每个主节点分配 1 个从节点。
    • 默认分配:6001/6002/6003 为主节点,其余为从节点。

3. 使用集群模式

普通连接:

redis-cli -p 6001
set a 100

报错:

(error) MOVED 15495 127.0.0.1:6003

原因:键值对根据插槽分配,不在当前节点。

解决:使用 集群模式连接

redis-cli -p 6001 -c

这样就会自动跳转到正确节点执行。

4. Java 对接

public static void main(String[] args) {
    // 和客户端一样,随便连一个节点即可
    try (JedisCluster cluster = new JedisCluster(new HostAndPort("127.0.0.1", 6001))) {
        System.out.println("集群实例数量:" + cluster.getClusterNodes().size());
        cluster.set("a", "yyds");
        System.out.println(cluster.get("a"));
    } catch (Exception e) {
        e.printStackTrace();
    }
}

5. 集群模式结构图

flowchart TD
    subgraph 集群
        A[Master6001<br/>slots 0-5460]
        B[Master6002<br/>slots 5461-10922]
        C[Master6003<br/>slots 10923-16383]
        A1[Slave7001]
        B1[Slave7002]
        C1[Slave7003]
    end

    A --> A1
    B --> B1
    C --> C1

    Client -->|set a=100| A
    Client -->|set b=200| B
    Client -->|set c=300| C

四、总结对比

模式特点优点缺点适用场景
主从复制主节点写,从节点读简单易用,读写分离无法自动故障转移读多写少
哨兵模式独立进程监控,主节点宕机自动切换高可用,自动切换主从部署复杂度增加高可用场景
集群模式插槽机制,数据分片,多个主节点水平扩展,解决数据量和并发瓶颈部署复杂度最高,跨 slot 较麻烦大规模数据存储,高并发场景