Redis 主从Master/Replica、哨兵Sentinel部署(docker-compose)及Spring Data Redis(Lettuce)集成

1. 引言

本文记录了Redis常用的主从Master/Replica、哨兵Sentinel模式的docker-compose部署以及Spring Redis Lettuce的代码集成配置示例。

集成模式适用场景节点要求Spring Data Redis - Lettuce支持
Master / Replica
主从复制
数据备份
读写分离
Master: 1
Replica: 1…N
配置一个节点(Master Or Replica)后自动获取其他节点,
亦可静态指定全部节点,
不支持自动故障切换。
Sentinel读写分离
高可用HA
自动故障切换Failover
Setinel: >=3
Master: 1
Replica: 1…N
静态指定全部sentinel节点,
且支持自动故障切换。
Cluster数据分片
读写分离
高可用HA
自动故障切换Failover
待续…

2. Master / Replica

主从复制,主负责写,从负责读,并不提供高可用HA及故障切换Failover。
官方文档:https://redis.io/docs/manual/replication

2.1 redis.conf相关配置

redis.conf中核心配置(REPLICATION):

详细配置说明可参见:https://github.com/redis/redis/blob/6.2/redis.conf

# 设置master ip和port
slaveof <masterip> <masterport>
# 设置master密码(master通过requirepass设置)
masterauth <master-password>
# slave与master连接断开或者还处在初始复制阶段时,是否提以供服务
# yes 返回旧数据 | no 返回错误SYNC(除了INFO和SLAVEOF命令)
slave-serve-stale-data yes
# Slave只读模式
# yes 推荐 | no
slave-read-only yes
# master端全量同步full synchronization(无法partial或者初始Slave连接)时,RDB文件是否经过master磁盘
# yes RDB不落盘 | no RDB落盘
repl-diskless-sync no
# diskless延迟同步时长(单位:秒),等待更多Slave到达,避免后到的Slave排队等待下一次RDB传输
# 默认5秒,设置0(即0秒)则立即开始同步
repl-diskless-sync-delay 5
# slave定时向master发送ping的时间间隔(单位:秒),默认10s
# repl-ping-slave-period 10
# slave端是否使用无磁盘记在RDB
# disabled 落盘RDB后再加载| on-empty-db 直接加载 | swapdb RAM拷贝
repl-diskless-load disabled

# 超时时长(单位:秒),需比repl-ping-slave-period长
# The following option sets the replication timeout for:
# 1) Bulk transfer I/O during SYNC, from the point of view of slave.
# 2) Master timeout from the point of view of slaves (data, pings).
# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings).
# repl-timeout 60
# 是否禁用TCP_NODELAY
repl-disable-tcp-nodelay no

# master端记录slave离线后的差异数据的日志大小(避免slave重连后进行全量同步)
# 仅有slave连接时才创建此日志
# repl-backlog-size 1mb
# backlog到期时长(单位:秒),即在指定时间范围内没有slave连接,则清理日志
# 0则表示一直保留
# repl-backlog-ttl 3600

# slave优先级,越小则表示优先级越大(默认100)
# Sentinel根据此优先级选举master,越小则优先被选举
# 0则表示不参与master选举
slave-priority 100
# 设置是否可被Sentinel报告显示:sentinel replicas <master>
# 此设置不影响参与master选举,若不想此replica参与master选举则需通过slave-priority 0进行设置
# replica-announced yes



# 少于指定已连接的slave数量则拒绝write请求
# 例如需要至少3个slave同时在线,并且lag <= 10s
# 默认0即禁用此机制
# min-slaves-to-write 3
# 超过多久未ping成功即为断开连接
# 默认10秒
# min-slaves-max-lag 10

# 特殊网络环境下设置replica的IP和Port
# replica-announce-ip 5.5.5.5
# replica-announce-port 1234

2.2 快速启动(docker-compose)

本示例基于Bitnami系列docker镜像bitnami/redis:6.2.6
https://hub.docker.com/r/bitnami/redis
https://github.com/bitnami/bitnami-docker-redis

Docker镜像bitnami/redis:6.2.6配置说明:

配置项(环境变量)说明对应redis.conf配置
REDIS_PORT_NUMBER当前Redis启动端口port <port>
REDIS_PASSWORD当前Redis节点密码requirepass <passw>
REDIS_REPLICATION_MODEReplication模式,即指定该容器为Master还是Slave,可选值:master | slave
REDIS_REPLICA_IPSlave的声明IP,默认$(get_machine_ip)返回容器IPreplica-announce-ip
REDIS_REPLICA_PORTSlave的声明port,默认REDIS_MASTER_PORT_NUMBERreplica-announce-port
REDIS_MASTER_HOSTMaster IP,用于Slave连接Masterslaveof <masterip> <masterport>
REDIS_MASTER_PORT_NUMBERMaster Port,用于Slave连接Master,默认6379slaveof <masterip> <masterport>
REDIS_MASTER_PASSWORDMaster 密码,用于Slave连接Master(亦可通过REDIS_MASTER_PASSWORD_FILE挂载密码内容文件)masterauth <master-password>

节点规划:

启动节点启动节点IP角色Redis映射Port
ubuntu-server-1192.168.3.101master6379
ubuntu-server-2192.168.3.102slave6381

Master docker-compose.yaml:

version: '2'
services:
  redis-master:
    image: bitnami/redis:6.2.6
    container_name: redis-master
    # 使用宿主机网络
    network_mode: host
    ports:
      - '6379'
    volumes:
      # 挂载数据目录
      - ./redis-data:/bitnami/redis/data
    environment:
      # 当前Redis自身的端口、密码等设置
      - REDIS_PORT_NUMBER=6379
      - REDIS_PASSWORD=mypassw123456
      # 当前Redis启动模式(master / slave)
      - REDIS_REPLICATION_MODE=master
      # 设置时区
      - TZ=Asia/Shanghai
                            

Replica(即Slave) docker-compose.yaml:

version: '2'
services:
  redis-replica:
    image: bitnami/redis:6.2.6
    container_name: redis-replica
    # 使用宿主机网络
    network_mode: host
    ports:
      - '6381'
    volumes:
      # 挂载数据目录
      - ./redis-data:/bitnami/redis/data
    environment:
      # 当前Redis自身的端口、密码等设置
      - REDIS_PORT_NUMBER=6381
      - REDIS_PASSWORD=mypassw123456
      # 当前Redis启动模式(master / slave)
      - REDIS_REPLICATION_MODE=slave
      # 此处配置对应Master相关配置(IP、Port、Password),可根据环境适当调整
      - REDIS_MASTER_HOST=192.168.3.101
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_PASSWORD=mypassw123456
      # 此处配置对应当前Replica的可被外部访问的声明IP和Port,可根据环境适当调整
      - REDIS_REPLICA_IP=192.168.3.102
      - REDIS_REPLICA_PORT=6381
      # 设置时区
      - TZ=Asia/Shanghai

分别在各自节点通过docker-compose up -d即可启动Redis Master和Slave节点。

docker-compose up -d

需要特别注意:

  • 此模式下Master仅有一个,后续可根据需要扩展添加新的Replica节点。
  • Master和Replica的密码(REDIS_PASSWORD、REDIS_MASTER_PASSWORD)需全部一样,否则Lettuce库无法分别设置密码。
  • 可通过REDIS_REPLICA_IP、REDIS_REPLICA_PORT声明Replica的IP和Port(适用于特殊网络环境,例如覆盖docker容器内部IP与Port为外部可访问的IP和Port),例如下图中没有正确设置IP和Port则通过info replication命令发现的即是Docker容器的内部IP,是无法直接被外部程序直接访问的。
    在这里插入图片描述

验证安装结果:

连接redis容器,执行如下命令查看节点状态:

# 查看Master/Replica信息
info replication
# 查询当前节点角色(master/replica)
role

在这里插入图片描述
在这里插入图片描述

亦可直接在Master上新加个Key,观察Replica是否自动同步包含相同的Key,若包含相同的Key则说明Master-Replica部署成功。

2.3 SpringBoot Redis代码集成

示例程序依赖Spring Boot 2.6.6(spring-boot-starter-data-redis - Lettuce实现)
旨在实现Redis读写分离的场景

配置文件application.yml示例

spring:
  # Spring Data Redis配置
  redis:
    client-type: lettuce
    # 此处仅配置一个Redis节点即可(Master Or Replica均可),Lettuce会根据info replication命令自定发现其他节点
    host: 192.168.3.101
    port: 6379
    password: mypassw123456
    database: 0
    # lettuce连接池配置
    lettuce:
      pool:
        enabled: true
        max-active: 8
        max-idle: 8
        min-idle: 5
        time-between-eviction-runs: 30s
        max-wait: 5s
      shutdown-timeout: 100ms

配置代码示例
开启Lettuce客户端读写分离配置代码示例:

@Configuration
public class SpringRedisConfig {

    /**
     * 开启Lettuce客户端读写分离配置(Write to Master, Read from Replica)
     */
    @Bean
    public LettuceClientConfigurationBuilderCustomizer lettuceClientConfigurationBuilderCustomizer() {
        return lettuceClientConfigurationBuilder -> {
            //从replica进行read操作(若replica不可用则回退到从master执行read操作)
            lettuceClientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
        };
    }
}

若无法通过一个Redis节点自动发现其他节点,例如通过info replication命令发现的为内部不可访问的Ip和Port、未正确设置replica-announce-ip和replica-announce-port等,则亦可以静态指定Redis相关节点(可被程序访问到的连接信息),配置示例代码如下:

@Configuration
public class SpringRedisConfig {

    /**
     * 自定义Lettuce连接工厂,
     * 静态指定Redis节点信息,
     * 开启Lettuce客户端读写分离配置(Write to Master, Read from Replica)
     */
    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
                //从replica进行read操作(若replica不可用则回退到从master执行read操作)
                .readFrom(ReadFrom.REPLICA_PREFERRED)
                .build();
        //静态指定Redis节点连接信息(声明时可先指定Master节点信息)
        RedisStaticMasterReplicaConfiguration staticMasterReplicaConfiguration = new RedisStaticMasterReplicaConfiguration("192.168.3.101", 6379);
        staticMasterReplicaConfiguration.setPassword("mypassw123456");
        //添加其他Replica节点信息
        staticMasterReplicaConfiguration.addNode("192.168.3.102", 6381);
        return new LettuceConnectionFactory(staticMasterReplicaConfiguration, clientConfig);
    }
}

注:
静态指定IP这种方式无法使用Redis Pub/Sub功能。
ERROR org.springframework.data.redis.listener.RedisMessageListenerContainer - Connection failure occurred. Restarting subscription task after 5000 ms
具体说明可参见:
https://docs.spring.io/spring-data/redis/docs/current/reference/html/#redis:write-to-master-read-from-replica在这里插入图片描述

验证程序执行结果

Lettuce通过info replication自动发现节点日志如下:
在这里插入图片描述

Lettuce执行读写分离日志如下:
在这里插入图片描述


3. Sentinel(哨兵)

Sentinel提供高可用的Master/Replica集群部署,
主从复制,主负责写,从负责读,并配合客户端可提供高可用HA及故障切换Failover。
官方文档:https://redis.io/docs/manual/sentinel/
Sentinel(独立于Redis)为可单独启动的进程,同样支持分布式部署,其主要功能如下:

  • 监控 Master、Replica健康状态
  • 通过API向用户、程序 通知 Master、Replica的异常状态
  • 自动故障切换,即当Sentinel检测到Master异常,即开启Failover进程
    • 从Replica中选举1个为新的Master
    • 通知其他Replica重新配置(重新redis.conf、sentinel.conf文件)使用新选举的Master
    • 通知其他连接对应Redis服务的应用程序重新配置使用新的连接地址(Master, Replica)
  • 配置提供者,可作为Redis客户端Client端服务发现的权限来源提供者。

3.1 sentinel.conf配置说明

Sentinel启动时需要提供对应的配置文件,通常名称为sentinel.conf:

# 启动方式1:通过redis-sentinel命令启动
redis-sentinel /path/to/sentinel.conf

# 启动方式2:通过redis-server命令以Sentinel模式启动
redis-server /path/to/sentinel.conf --sentinel

Sentinel亦会将状态信息保存到此配置文件中,Sentinel重启后会加载此文件。

sentinel.conf核心配置说明

详细配置说明可参见:https://github.com/redis/redis/blob/6.2/sentinel.conf

# Sentinel启动端口
port 26379

# 保护模式(默认关闭,即允许除localhost外的访问)
protected-mode no

# daemonized 守护进程启动
daemonize no
# daemonize启动时会将pid写入此文件
pidfile /var/run/redis-sentinel.pid
# 日志文件目录,空则输出到标准输出流。
logfile ""

# 声明Sentinel的IP和Port,适用于特殊网络环境下设置Sentinel的IP和Port
# sentinel announce-ip <ip>
# sentinel announce-port <port>

# 工作目录
dir /tmp

# =======================================================================
# ======================= Sentinel核心配置 ===============================
# =======================================================================
# 格式:sentinel monitor <master-name> <ip> <redis-port> <quorum>
# master-name格式:[A-z0-9.-_]
# 设置sentinel监控的集群(通过集群名<master-name>进行区分)的Master连接信息,
# 无需提供Replica信息,sentinel会自动发现其他Replica节点,
# 并且仅当至少指定数量(<quorum>)的sentinel节点认为Master节点不可用S_DOWN,才会真正认为Master异常O_DOWN(Objectively Down),
# 并且仅当sentinel节点数量过半(与<quorum>无关)才会真正触发Failover(选举新的Master节点)
sentinel monitor mymaster 127.0.0.1 6379 2

# 格式:sentinel auth-pass <master-name> <password>
# 格式:sentinel auth-user <master-name> <username>
# 设置被监控的Redis集群的连接密码信息(Master/Replica密码需相同)
# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd


# 格式:sentinel down-after-milliseconds <master-name> <milliseconds>
# 设置Master不可连接超过指定时间后,即认为Master异常S_DOWN(Subjectively Down)
# 默认30秒
sentinel down-after-milliseconds mymaster 30000

# 设置sentinel自身的密码(多Sentinel需密码相同)
# requirepass <password>
# sentinel sentinel-user <username>

# 格式:sentinel parallel-syncs <master-name> <numreplicas>
# 设置同时向新选举的Master进行同步操作的的Replica数量,
# Replica在同步过程中存在阻塞,影响查询操作,
# 可以使用较低数值减少查询阻塞(保留多余的Replica依旧提供查询服务)
sentinel parallel-syncs mymaster 1

# 格式:sentinel failover-timeout <master-name> <milliseconds>
# 设置Failover的超时时长,默认3分钟。
sentinel failover-timeout mymaster 180000

3.2 快速启动(docker-compose)

本示例基于Bitnami系列docker镜像

Docker镜像bitnami/redis-sentinel:6.2.6配置说明:

配置项(环境变量)说明对应sentinel.conf配置
REDIS_MASTER_SET待监控的Redis Master名称,
默认mymaster
sentinel monitor <master-name> <ip> <redis-port> <quorum>
REDIS_MASTER_HOST待监控的Redis Master IPsentinel monitor <master-name> <ip> <redis-port> <quorum>
REDIS_MASTER_PORT_NUMBER待监控的Redis Master端口,
默认6379
sentinel monitor <master-name> <ip> <redis-port> <quorum>
REDIS_SENTINEL_QUORUM即多少个Sentinel实例检测到Master异常S_DOWN才认为Master真正不可达O_DOWN,
默认2
sentinel monitor <master-name> <ip> <redis-port> <quorum>
REDIS_MASTER_PASSWORD被监控的Redis Master的连接密码sentinel auth-pass <master-name> <password>
REDIS_MASTER_USER被监控的Redis Master的连接用户名sentinel auth-user <master-name> <username>
REDIS_SENTINEL_PORT_NUMBERSentinel启动端口,
默认26379
port <sentinel-port>
REDIS_SENTINEL_PASSWORDSentinel自身的认证密码
REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS即Master多久不可用才被认为异常S_DOWN,
默认60000(1分钟)
sentinel down-after-milliseconds <master-name><milliseconds>
REDIS_SENTINEL_FAILOVER_TIMEOUTFailover超时,
默认180000(3分钟)
sentinel failover-timeout <master-name> <milliseconds>
REDIS_SENTINEL_ANNOUNCE_IP声明Sentinel的IP,适用于特殊网络环境下设置Sentinel的IPsentinel announce-ip <ip>
REDIS_SENTINEL_ANNOUNCE_PORT声明Sentinel的Port,适用于特殊网络环境下设置Sentinel的Port,
默认使用REDIS_SENTINEL_PORT_NUMBER配置
sentinel announce-port <port>

节点规划:

启动节点启动节点IP角色Redis映射Port
ubuntu-server-1192.168.3.101master + sentinelredis: 6379
sentinel: 26379
ubuntu-server-2192.168.3.102slave + sentinelredis: 6381
sentinel: 26381
ubuntu-server-2192.168.3.102slave + sentinelredis: 6382
sentinel: 26382
方式1 - 使用环境变量配置【此方式有问题,若不感兴趣可直接跳到 - 方式2】

注:
使用此方式部署后,sentinel在重启后会出现问题,
实际部署可采用 - 方式2。

Master docker-compose.yaml:

version: '2'
services:
  redis-master:
    image: bitnami/redis:6.2.6
    container_name: redis-master
    # 使用宿主机网络
    network_mode: host
    ports:
      - '6379'
    volumes:
      # 挂载数据目录
      - ./redis-data:/bitnami/redis/data
    environment:
      # 当前Replica自身的端口、密码等设置
      - REDIS_PORT_NUMBER=6379
      - REDIS_PASSWORD=mypassw123456
      # 当前Redis启动模式(master / slave)
      - REDIS_REPLICATION_MODE=master
      # 此处配置对应当前Replica的可被外部访问的声明IP和Port,可根据环境适当调整
      # 在Master Down掉后再重启便会成为Slave,此时需要用到此配置
      - REDIS_REPLICA_IP=192.168.3.101
      - REDIS_REPLICA_PORT=6379
      # 设置时区
      - TZ=Asia/Shanghai
  redis-sentinel:
    image: bitnami/redis-sentinel:6.2.6
    container_name: redis-sentinel
    # 使用宿主机网络
    network_mode: host
    ports:
      - '26379'
    environment:
      # 设置sentinel启动端口、认证密码等
      - REDIS_SENTINEL_PORT_NUMBER=26379
      - REDIS_SENTINEL_PASSWORD=mypassw123456
      # 设置被监控的Redis Maser信息
      - REDIS_MASTER_SET=luo-sentinel-master
      - REDIS_MASTER_HOST=192.168.3.101
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_SENTINEL_QUORUM=2
      - REDIS_MASTER_PASSWORD=mypassw123456
      # 设置Sentinel S_DOWN检测时间(即超过多久未收到PING响应则认为异常)
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=5000
      # 此处配置对应当前Sentinel的可被外部访问的声明IP和Port,可根据环境适当调整
      - REDIS_SENTINEL_ANNOUNCE_IP=192.168.3.101
      - REDIS_SENTINEL_ANNOUNCE_PORT=26379
      # 设置时区
      - TZ=Asia/Shanghai

Replica-1 docker-compose.yaml:

version: '2'
services:
  redis-replica:
    image: bitnami/redis:6.2.6
    container_name: redis-replica-1
    # 使用宿主机网络
    network_mode: host
    ports:
      - '6381'
    volumes:
      - ./redis-data:/bitnami/redis/data
    environment:
      # 当前Redis自身的端口、密码等设置
      - REDIS_PORT_NUMBER=6381
      - REDIS_PASSWORD=mypassw123456
      # REDIS启动模式(master/slave)
      - REDIS_REPLICATION_MODE=slave
      # 此处配置对应Master相关配置(IP、Port、Password),可根据环境适当调整
      - REDIS_MASTER_HOST=192.168.3.101
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_PASSWORD=mypassw123456
      # 此处配置对应当前Replica的可被外部访问的声明IP和Port,可根据环境适当调整
      - REDIS_REPLICA_IP=192.168.3.102
      - REDIS_REPLICA_PORT=6381
      # 设置时区
      - TZ=Asia/Shanghai
  redis-sentinel:
    image: bitnami/redis-sentinel:6.2.6
    container_name: redis-sentinel-1
    # 使用宿主机网络
    network_mode: host
    ports:
      - '26381'
    environment:
      # 设置sentinel启动端口、认证密码
      - REDIS_SENTINEL_PORT_NUMBER=26381
      - REDIS_SENTINEL_PASSWORD=mypassw123456
      # 设置被监控的Redis Maser信息
      - REDIS_MASTER_SET=luo-sentinel-master
      - REDIS_MASTER_HOST=192.168.3.101
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_SENTINEL_QUORUM=2
      - REDIS_MASTER_PASSWORD=mypassw123456
      # 设置Sentinel S_DOWN检测时间(即超过多久未收到PING响应则认为异常)
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=5000
      # 此处配置对应当前Sentinel的可被外部访问的声明IP和Port,可根据环境适当调整
      - REDIS_SENTINEL_ANNOUNCE_IP=192.168.3.102
      - REDIS_SENTINEL_ANNOUNCE_PORT=26381
      # 设置时区
      - TZ=Asia/Shanghai

Replica-2 docker-compose.yaml:

version: '2'
services:
  redis-replica:
    image: bitnami/redis:6.2.6
    container_name: redis-replica-2
    # 使用宿主机网络
    network_mode: host
    ports:
      - '6382'
    volumes:
      - ./redis-data:/bitnami/redis/data
    environment:
      # 当前Redis自身的端口、密码等设置
      - REDIS_PORT_NUMBER=6382
      - REDIS_PASSWORD=mypassw123456
      # REDIS启动模式(master/slave)
      - REDIS_REPLICATION_MODE=slave
      # 此处配置对应Master相关配置(IP、Port、Password),可根据环境适当调整
      - REDIS_MASTER_HOST=192.168.3.101
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_PASSWORD=mypassw123456
      # 此处配置对应当前Replica的可被外部访问的声明IP和Port,可根据环境适当调整
      - REDIS_REPLICA_IP=192.168.3.102
      - REDIS_REPLICA_PORT=6382
      # 设置时区
      - TZ=Asia/Shanghai
  redis-sentinel:
    image: bitnami/redis-sentinel:6.2.6
    container_name: redis-sentinel-2
    # 使用宿主机网络
    network_mode: host
    ports:
      - '26382'
    environment:
      # 设置sentinel启动端口、认证密码
      - REDIS_SENTINEL_PORT_NUMBER=26382
      - REDIS_SENTINEL_PASSWORD=mypassw123456
      # 设置被监控的Redis Maser信息
      - REDIS_MASTER_SET=luo-sentinel-master
      - REDIS_MASTER_HOST=192.168.3.101
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_SENTINEL_QUORUM=2
      - REDIS_MASTER_PASSWORD=mypassw123456
      # 设置Sentinel S_DOWN检测时间(即超过多久未收到PING响应则认为异常)
      - REDIS_SENTINEL_DOWN_AFTER_MILLISECONDS=5000
      # 此处配置对应当前Sentinel的可被外部访问的声明IP和Port,可根据环境适当调整
      - REDIS_SENTINEL_ANNOUNCE_IP=192.168.3.102
      - REDIS_SENTINEL_ANNOUNCE_PORT=26382
      # 设置时区
      - TZ=Asia/Shanghai

此种方式部署后,在Sentinel重启后,Sentinel状态异常如下图:
在这里插入图片描述

之后Master再次挂掉后,既无法选取新的Master,选举Master异常日志如下:
在这里插入图片描述

由于Sentinel会重写sentinel.conf文件,猜测该文件有持久化的作用,
而使用此方法每次重启后持久化状态丢失,
所以最终调整方案将此配置文件挂载出来,可参见方式2。


方式2 - 挂载sentinel.conf配置文件

该方式通过自定义sentinel.conf配置文件并挂载进容器对应位置,
在重启sentinel容器后,可重复读取之前已被sentinel修改过的sentinel.conf文件。

Master docker-compose.yaml:

version: '2'
services:
  redis-master:
    image: bitnami/redis:6.2.6
    container_name: redis-master
    # 使用宿主机网络
    network_mode: host
    ports:
      - '6379'
    volumes:
      # 挂载数据目录
      - ./redis-data:/bitnami/redis/data
    environment:
      # 当前Redis自身的端口、密码等设置
      - REDIS_PORT_NUMBER=6379
      - REDIS_PASSWORD=mypassw123456
      # 当前Redis启动模式(master / slave)
      - REDIS_REPLICATION_MODE=master
      # 此处配置对应当前Replica的可被外部访问的声明IP和Port,可根据环境适当调整
      # 在Master Down掉后再重启便会成为Slave,此时需要用到此配置
      - REDIS_REPLICA_IP=192.168.3.101
      - REDIS_REPLICA_PORT=6379
      # 设置时区
      - TZ=Asia/Shanghai
  redis-sentinel:
    image: bitnami/redis-sentinel:6.2.6
    container_name: redis-sentinel
    # 使用宿主机网络
    network_mode: host
    ports:
      - '26379'
    volumes:
      # 挂载sentinel配置文件./redis-sentinel/conf/sentinel.conf
      - ./sentinel-data:/bitnami
    environment:
      # 设置时区
      - TZ=Asia/Shanghai

Master ./sentinel-data/redis-sentinel/conf/sentinel.conf

# Sentinel启动端口
port 26379
# 绑定地址(任意IP V4均可)
bind 0.0.0.0
# 保护模式(默认关闭,即允许除localhost外的访问)
daemonize no
# 设置sentinel自身的密码(多Sentinel需密码相同)
requirepass "mypassw123456"
# daemonize启动时会将pid写入此文件
pidfile "/opt/bitnami/redis-sentinel/tmp/redis-sentinel.pid"
# 日志文件目录,空则输出到标准输出流。
logfile ""
# 工作目录
dir "/tmp"

# =======================================================================
# ======================= Sentinel核心配置 ===============================
# =======================================================================
# 格式:sentinel monitor <master-name> <ip> <redis-port> <quorum>
# master-name格式:[A-z0-9.-_]
# 设置sentinel监控的集群(通过集群名<master-name>进行区分)的Master连接信息,
# 无需提供Replica信息,sentinel会自动发现其他Replica节点,
# 并且仅当至少指定数量(<quorum>)的sentinel节点认为Master节点不可用S_DOWN,才会真正认为Master异常O_DOWN(Objectively Down),
# 并且仅当sentinel节点数量过半(与<quorum>无关)才会真正触发Failover(选举新的Master节点)
sentinel monitor luo-sentinel-master 192.168.3.101 6379 2

# 格式:sentinel down-after-milliseconds <master-name> <milliseconds>
# 设置Master不可连接超过指定时间后,即认为Master异常S_DOWN(Subjectively Down)
# 默认30秒
sentinel down-after-milliseconds luo-sentinel-master 5000

# 格式:sentinel auth-pass <master-name> <password>
# 格式:sentinel auth-user <master-name> <username>
# 设置被监控的Redis集群的连接密码信息(Master/Replica密码需相同)
sentinel auth-pass luo-sentinel-master mypassw123456

# 声明Sentinel的IP和Port,适用于特殊网络环境下设置Sentinel的IP和Port
sentinel announce-ip "192.168.3.101"
sentinel announce-port 26379


# 其他默认配置
sentinel deny-scripts-reconfig yes
sentinel resolve-hostnames yes
sentinel announce-hostnames no
acllog-max-len 128

Replica-1 docker-compose.yaml:

version: '2'
services:
  redis-replica:
    image: bitnami/redis:6.2.6
    container_name: redis-replica-1
    # 使用宿主机网络
    network_mode: host
    ports:
      - '6381'
    volumes:
      - ./redis-data:/bitnami/redis/data
    environment:
      # 当前Redis自身的端口、密码等设置
      - REDIS_PORT_NUMBER=6381
      - REDIS_PASSWORD=mypassw123456
      # 当前Redis启动模式(master / slave)
      - REDIS_REPLICATION_MODE=slave
      # 此处配置对应Master相关配置(IP、Port、Password),可根据环境适当调整
      - REDIS_MASTER_HOST=192.168.3.101
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_PASSWORD=mypassw123456
      # 此处配置对应当前Replica的可被外部访问的声明IP和Port,可根据环境适当调整
      - REDIS_REPLICA_IP=192.168.3.102
      - REDIS_REPLICA_PORT=6381
      # 设置时区
      - TZ=Asia/Shanghai
  redis-sentinel:
    image: bitnami/redis-sentinel:6.2.6
    container_name: redis-sentinel-1
    # 使用宿主机网络
    network_mode: host
    ports:
      - '26381'
    volumes:
      # 挂载sentinel配置文件./redis-sentinel/conf/sentinel.conf
      - ./sentinel-data:/bitnami
    environment:
      # 设置时区
      - TZ=Asia/Shanghai

Replica-1 ./sentinel-data/redis-sentinel/conf/sentinel.conf

# Sentinel启动端口
port 26381
# 绑定地址(任意IP V4均可)
bind 0.0.0.0
# 保护模式(默认关闭,即允许除localhost外的访问)
daemonize no
# 设置sentinel自身的密码(多Sentinel需密码相同)
requirepass "mypassw123456"
# daemonize启动时会将pid写入此文件
pidfile "/opt/bitnami/redis-sentinel/tmp/redis-sentinel.pid"
# 日志文件目录,空则输出到标准输出流。
logfile ""
# 工作目录
dir "/tmp"

# =======================================================================
# ======================= Sentinel核心配置 ===============================
# =======================================================================
# 格式:sentinel monitor <master-name> <ip> <redis-port> <quorum>
# master-name格式:[A-z0-9.-_]
# 设置sentinel监控的集群(通过集群名<master-name>进行区分)的Master连接信息,
# 无需提供Replica信息,sentinel会自动发现其他Replica节点,
# 并且仅当至少指定数量(<quorum>)的sentinel节点认为Master节点不可用S_DOWN,才会真正认为Master异常O_DOWN(Objectively Down),
# 并且仅当sentinel节点数量过半(与<quorum>无关)才会真正触发Failover(选举新的Master节点)
sentinel monitor luo-sentinel-master 192.168.3.101 6379 2

# 格式:sentinel down-after-milliseconds <master-name> <milliseconds>
# 设置Master不可连接超过指定时间后,即认为Master异常S_DOWN(Subjectively Down)
# 默认30秒
sentinel down-after-milliseconds luo-sentinel-master 5000

# 格式:sentinel auth-pass <master-name> <password>
# 格式:sentinel auth-user <master-name> <username>
# 设置被监控的Redis集群的连接密码信息(Master/Replica密码需相同)
sentinel auth-pass luo-sentinel-master mypassw123456

# 声明Sentinel的IP和Port,适用于特殊网络环境下设置Sentinel的IP和Port
sentinel announce-ip "192.168.3.102"
sentinel announce-port 26381


# 其他默认配置
sentinel deny-scripts-reconfig yes
sentinel resolve-hostnames yes
sentinel announce-hostnames no
acllog-max-len 128

Replica-2 docker-compose.yaml:

version: '2'
services:
  redis-replica:
    image: bitnami/redis:6.2.6
    container_name: redis-replica-2
    # 使用宿主机网络
    network_mode: host
    ports:
      - '6382'
    volumes:
      - ./redis-data:/bitnami/redis/data
    environment:
      # 当前Redis自身的端口、密码等设置
      - REDIS_PORT_NUMBER=6382
      - REDIS_PASSWORD=mypassw123456
      # 当前Redis启动模式(master / slave)
      - REDIS_REPLICATION_MODE=slave
      # 此处配置对应Master相关配置(IP、Port、Password),可根据环境适当调整
      - REDIS_MASTER_HOST=192.168.3.101
      - REDIS_MASTER_PORT_NUMBER=6379
      - REDIS_MASTER_PASSWORD=mypassw123456
      # 此处配置对应当前Replica的可被外部访问的声明IP和Port,可根据环境适当调整
      - REDIS_REPLICA_IP=192.168.3.102
      - REDIS_REPLICA_PORT=6382
      # 设置时区
      - TZ=Asia/Shanghai
  redis-sentinel:
    image: bitnami/redis-sentinel:6.2.6
    container_name: redis-sentinel-2
    # 使用宿主机网络
    network_mode: host
    ports:
      - '26382'
    volumes:
      # 挂载sentinel配置文件./redis-sentinel/conf/sentinel.conf
      - ./sentinel-data:/bitnami
    environment:
      # 设置时区
      - TZ=Asia/Shanghai

Replica-2 ./sentinel-data/redis-sentinel/conf/sentinel.conf

# Sentinel启动端口
port 26382
# 绑定地址(任意IP V4均可)
bind 0.0.0.0
# 保护模式(默认关闭,即允许除localhost外的访问)
daemonize no
# 设置sentinel自身的密码(多Sentinel需密码相同)
requirepass "mypassw123456"
# daemonize启动时会将pid写入此文件
pidfile "/opt/bitnami/redis-sentinel/tmp/redis-sentinel.pid"
# 日志文件目录,空则输出到标准输出流。
logfile ""
# 工作目录
dir "/tmp"

# =======================================================================
# ======================= Sentinel核心配置 ===============================
# =======================================================================
# 格式:sentinel monitor <master-name> <ip> <redis-port> <quorum>
# master-name格式:[A-z0-9.-_]
# 设置sentinel监控的集群(通过集群名<master-name>进行区分)的Master连接信息,
# 无需提供Replica信息,sentinel会自动发现其他Replica节点,
# 并且仅当至少指定数量(<quorum>)的sentinel节点认为Master节点不可用S_DOWN,才会真正认为Master异常O_DOWN(Objectively Down),
# 并且仅当sentinel节点数量过半(与<quorum>无关)才会真正触发Failover(选举新的Master节点)
sentinel monitor luo-sentinel-master 192.168.3.101 6379 2

# 格式:sentinel down-after-milliseconds <master-name> <milliseconds>
# 设置Master不可连接超过指定时间后,即认为Master异常S_DOWN(Subjectively Down)
# 默认30秒
sentinel down-after-milliseconds luo-sentinel-master 5000

# 格式:sentinel auth-pass <master-name> <password>
# 格式:sentinel auth-user <master-name> <username>
# 设置被监控的Redis集群的连接密码信息(Master/Replica密码需相同)
sentinel auth-pass luo-sentinel-master mypassw123456

# 声明Sentinel的IP和Port,适用于特殊网络环境下设置Sentinel的IP和Port
sentinel announce-ip "192.168.3.102"
sentinel announce-port 26382


# 其他默认配置
sentinel deny-scripts-reconfig yes
sentinel resolve-hostnames yes
sentinel announce-hostnames no
acllog-max-len 128

分别在各自节点通过docker-compose up -d即可启动Redis Master和Slave节点。

docker-compose up -d

需要特别注意:

  • 此模式下Master仅有一个,后续可根据需要扩展添加新的Replica节点。
  • Master和Replica的密码(REDIS_PASSWORD、REDIS_MASTER_PASSWORD)需全部一样,否则Lettuce库无法分别设置密码。
  • 可通过REDIS_REPLICA_IP、REDIS_REPLICA_PORT声明Replica的IP和Port(适用于特殊网络环境,例如覆盖docker容器内部IP与Port为外部可访问的IP和Port),例如下图中没有正确设置IP和Port则通过info replication命令发现的即是Docker容器的内部IP,是无法直接被外部程序直接访问的。

注:上面几条和之前Master/Replica模式相同,下面的为Sentinel需要注意的。

  • 多个Sentinel的自身认证密码requirepass需全部一样。
  • 可通过sentinel announce-ip、sentinel announce-port声明Sentinel的IP和Port(适用于特殊网络环境,例如覆盖docker容器内部IP与Port为外部可访问的IP和Port)。

验证安装结果:

连接Sentinel容器,执行如下命令查看节点状态:

# 进入Sentinel Docker容器,通过redis-cli连接Sentinel
redis-cli -h 127.0.0.1 -p 26379 -a mypassw123456
# 然后执行如下命令
# 查看Sentinel监控的Master信息
# 其中的luo-sentinel-master对应之前docker-compose.yaml文件中设置的Master名称
sentinel master luo-sentinel-master

# 查看连接到Master的Replica信息
sentinel replicas mymaster
# 查看其它Sentinel节点信息
sentinel sentinels mymaster

在这里插入图片描述

3.3 SpringBoot Redis代码集成

示例程序依赖Spring Boot 2.6.6(spring-boot-starter-data-redis - Lettuce实现)
旨在实现Redis读写分离的场景

配置文件application.yml示例

spring:
  # Spring Data Redis配置
  redis:
    sentinel:
      # sentinel Master名称
      master: luo-sentinel-master
      # sentinel连接密码
      password: mypassw123456
      # sentinel节点
      nodes:
        - 192.168.3.101:26379
        - 192.168.3.102:26381
        - 192.168.3.102:26382
    # 此处设置Redis连接密码
    password: mypassw123456
    client-type: lettuce   
    database: 0
    # lettuce连接池配置
    lettuce:
      pool:
        enabled: true
        max-active: 8
        max-idle: 8
        min-idle: 5
        time-between-eviction-runs: 30s
        max-wait: 5s
      shutdown-timeout: 100ms

配置代码示例
开启Lettuce客户端读写分离配置代码示例:

@Configuration
public class SpringRedisConfig {

    /**
     * 开启Lettuce客户端读写分离配置(Write to Master, Read from Replica)
     */
    @Bean
    public LettuceClientConfigurationBuilderCustomizer lettuceClientConfigurationBuilderCustomizer() {
        return lettuceClientConfigurationBuilder -> {
            //从replica进行read操作(若replica不可用则回退到从master执行read操作)
            lettuceClientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
        };
    }
}

验证程序执行结果

Lettuce通过sentinel mastersentinel slaves(>=5.0后为sentinel replicas)自动发现节点日志如下:
在这里插入图片描述
Lettuce执行读写分离日志如下:
在这里插入图片描述

3.4 测试Sentinel自动故障切换

我测试的方法比较暴力,我直接把Master节点192.168.3.101上的Redis Master和Sentinel容器直接停掉,

docker-compose down

此观察Replica节点192.168.3.102上的Sentinel容器日志:

# 查看其它任一存活的sentinel日志(本文中提到的redis-sentinel-1和redis-sentinel-2均可)
docker logs -f redis-sentinel-2

在这里插入图片描述

在切换过程中也可以通过sentinel master | replicas查看对应的节点状态:
在这里插入图片描述

Lettuce监听Sentinel自动故障切换日志如下:

Sentinel间每隔2秒过向Channel频道__sentinel__:hello发送消息(ip, port, runid、current config等)实现自动发现,
且每个Sentinel都订阅所有Master / Replica的对应Channel频道__sentinel__:hello,并且Sentinel收到新的配置版本后会自动覆盖旧版本。
且Lettuce订阅sentinel对应的相关Channel,如+sdown, +odown, +switch-master,…,通过订阅相关频道以便第一时间感知节点变化,
且配合sentinel master, sentinel replicas等命令第一时间获取最新的Master / Replica分布,实现自动切换新的Master和Replica。

在这里插入图片描述

Lettuce查询新的Master / Replica信息:
在这里插入图片描述

之后再通过Lettuce执行Redis请求,可发现已自动完成Master / Replica切换,如下图:
在这里插入图片描述
自己也可以多试几次切换看看效果。


后续

后续会单独再开一遍博客记录Cluster模式…


参考:
https://docs.spring.io/spring-boot/docs/2.6.6/reference/htmlsingle/#application-properties.data.spring.redis.client-name
https://docs.spring.io/spring-boot/docs/2.6.6/reference/htmlsingle/#data.nosql.redis
https://docs.spring.io/spring-data/redis/docs/current/reference/html/#redis
https://www.baeldung.com/spring-data-redis-properties
https://www.baeldung.com/spring-boot-redis-cache
https://www.baeldung.com/spring-embedded-redis
https://www.vinsguru.com/redis-master-slave-with-spring-boot
https://docs.spring.io/spring-data/redis/docs/current/reference/html/#redis:write-to-master-read-from-replica
https://programs.wiki/wiki/springboot-redis-master-slave-replication-sentinel-and-read-write-separation.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗小爬EX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值