Redis 哨兵模式高可用集群搭建完整教程

前言

Redis 哨兵(Sentinel)模式是 Redis 官方推荐的高可用解决方案。它通过监控主从节点、自动故障转移、配置中心等功能,确保 Redis 服务在节点故障时能够自动恢复,保障业务连续性。本文将详细介绍 Redis 哨兵模式的完整搭建过程。

一、环境准备

1.1 服务器规划

本教程使用 3 台服务器搭建 Redis 哨兵集群:

服务器 IP 地址 角色 端口
node1 192.168.1.101 Master + Sentinel 6379 + 26379
node2 192.168.1.102 Slave + Sentinel 6379 + 26379
node3 192.168.1.103 Slave + Sentinel 6379 + 26379

1.2 系统要求

  • 操作系统:CentOS 7+ / Ubuntu 18.04+
  • Redis 版本:6.0+(推荐 7.0+)
  • 内存:每节点至少 2GB
  • 网络:节点间可互相访问

二、安装 Redis

2.1 下载 Redis

在所有节点上执行以下命令:

cd /usr/local/src
wget https://download.redis.io/releases/redis-7.2.3.tar.gz
tar -zxvf redis-7.2.3.tar.gz
cd redis-7.2.3

2.2 编译安装

# 编译
make MALLOC=libc

# 安装到指定目录
make PREFIX=/usr/local/redis install

# 创建数据目录
mkdir -p /usr/local/redis/data
mkdir -p /usr/local/redis/logs

2.3 配置环境变量

# 添加到 PATH
echo 'export PATH=$PATH:/usr/local/redis/bin' >> /etc/profile
source /etc/profile

# 验证安装
redis-server --version

三、配置 Redis 主从复制

3.1 Master 节点配置 (node1)

创建 Redis 配置文件 /usr/local/redis/redis.conf

# 基础配置
bind 0.0.0.0
port 6379
daemonize yes
pidfile /var/run/redis_6379.pid
logfile "/usr/local/redis/logs/redis.log"
dir /usr/local/redis/data

# 持久化配置
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

# 安全配置
requirepass "YourStrongPassword123!"
masterauth "YourStrongPassword123!"

# 内存配置
maxmemory 2gb
maxmemory-policy allkeys-lru

# 日志级别
loglevel notice

3.2 Slave 节点配置 (node2, node3)

Slave 节点配置与 Master 基本相同,需要额外添加主从复制配置:

# 基础配置(同上)
bind 0.0.0.0
port 6379
daemonize yes
pidfile /var/run/redis_6379.pid
logfile "/usr/local/redis/logs/redis.log"
dir /usr/local/redis/data

# 主从复制配置
replicaof 192.168.1.101 6379
masterauth "YourStrongPassword123!"

# 持久化配置
requirepass "YourStrongPassword123!"
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec

# 内存配置
maxmemory 2gb
maxmemory-policy allkeys-lru

3.3 启动 Redis 服务

在所有节点上启动 Redis:

# 启动 Redis
/usr/local/redis/bin/redis-server /usr/local/redis/redis.conf

# 检查进程
ps aux | grep redis

# 检查端口
netstat -tlnp | grep 6379

3.4 验证主从复制

在 Master 节点上检查:

redis-cli -a "YourStrongPassword123!" info replication

输出示例:

# Replication
role:master
connected_slaves:2
slave0:ip=192.168.1.102,port=6379,state=online,offset=12345,lag=0
slave1:ip=192.168.1.103,port=6379,state=online,offset=12345,lag=0

四、配置 Redis Sentinel

4.1 创建 Sentinel 配置文件

在所有节点上创建 /usr/local/redis/sentinel.conf

# Sentinel 端口
port 26379
bind 0.0.0.0
daemonize yes
pidfile /var/run/redis-sentinel.pid
logfile "/usr/local/redis/logs/sentinel.log"
dir /usr/local/redis/data

# 监控配置
# sentinel monitor    
sentinel monitor mymaster 192.168.1.101 6379 2

# 认证配置
sentinel auth-pass mymaster YourStrongPassword123!

# 故障判定时间(毫秒)
# 主观下线时间
sentinel down-after-milliseconds mymaster 5000
# 故障转移超时时间
sentinel failover-timeout mymaster 60000
# 并行同步的 slave 数量
sentinel parallel-syncs mymaster 1

# 通知脚本(可选)
# sentinel notification-script mymaster /usr/local/redis/notify.sh

# 重新配置脚本(可选)
# sentinel client-reconfig-script mymaster /usr/local/redis/reconfig.sh

4.2 配置文件详解

配置项 说明 推荐值
sentinel monitor 监控的主节点,quorum 是判定主节点下线的票数 3 节点设为 2
down-after-milliseconds 多久判定节点下线 5000-10000ms
failover-timeout 故障转移超时时间 60000ms
parallel-syncs 故障转移时并行同步的 slave 数 1

4.3 启动 Sentinel

在所有节点上启动 Sentinel:

# 启动 Sentinel
/usr/local/redis/bin/redis-sentinel /usr/local/redis/sentinel.conf

# 检查进程
ps aux | grep sentinel

# 检查端口
netstat -tlnp | grep 26379

4.4 验证 Sentinel 状态

# 查看监控信息
redis-cli -p 26379 sentinel master mymaster

# 查看 slave 列表
redis-cli -p 26379 sentinel slaves mymaster

# 查看 Sentinel 列表
redis-cli -p 26379 sentinel sentinels mymaster

五、高可用测试

5.1 写入测试数据

# 连接到 Master
redis-cli -h 192.168.1.101 -p 6379 -a "YourStrongPassword123!"

# 写入测试数据
127.0.0.1:6379> set test_key "Hello Redis Sentinel"
OK

# 验证数据
127.0.0.1:6379> get test_key
"Hello Redis Sentinel"

5.2 模拟 Master 故障

# 在 node1 上停止 Redis Master
killall redis-server

# 或者模拟宕机
shutdown -h now

5.3 观察故障转移

在 Sentinel 节点上查看日志:

tail -f /usr/local/redis/logs/sentinel.log

关键日志输出:

+sdown master mymaster 192.168.1.101 6379
+odown master mymaster 192.168.1.101 6379 #quorum 2/2
+new-epoch 1
+try-failover master mymaster 192.168.1.101 6379
+vote-for-leader abc123 1
+elected-leader master mymaster 192.168.1.101 6379
+failover-state-select-slave master mymaster 192.168.1.101 6379
+selected-slave slave 192.168.1.102:6379
+failover-state-send-slaveof-noone slave 192.168.1.102:6379
+failover-state-reconf-slaves slave 192.168.1.102:6379
+failover-end master mymaster 192.168.1.101 6379
+switch-master mymaster 192.168.1.101 6379 192.168.1.102 6379

5.4 验证新 Master

# 查看当前 Master
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster

# 输出:
# 1) "192.168.1.102"
# 2) "6379"

# 连接到新 Master 验证数据
redis-cli -h 192.168.1.102 -p 6379 -a "YourStrongPassword123!" get test_key

5.5 恢复原 Master

启动原 Master 节点后,它会自动成为 Slave:

# 启动 Redis
/usr/local/redis/bin/redis-server /usr/local/redis/redis.conf

# 查看角色(已变为 Slave)
redis-cli -h 192.168.1.101 -p 6379 -a "YourStrongPassword123!" info replication

六、客户端连接配置

6.1 Python 客户端连接

import redis
from redis.sentinel import Sentinel

# Sentinel 连接配置
sentinel = Sentinel(
    [('192.168.1.101', 26379),
     ('192.168.1.102', 26379),
     ('192.168.1.103', 26379)],
    socket_timeout=0.1,
    password='YourStrongPassword123!'
)

# 获取 Master 连接(用于写操作)
master = sentinel.master_for(
    'mymaster',
    socket_timeout=0.1,
    password='YourStrongPassword123!'
)

# 获取 Slave 连接(用于读操作)
slave = sentinel.slave_for(
    'mymaster',
    socket_timeout=0.1,
    password='YourStrongPassword123!'
)

# 写操作
master.set('foo', 'bar')

# 读操作
value = slave.get('foo')
print(value)

6.2 Java 客户端连接 (Jedis)

import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.Jedis;

import java.util.HashSet;
import java.util.Set;

public class RedisSentinelExample {
    public static void main(String[] args) {
        // Sentinel 节点
        Set sentinels = new HashSet<>();
        sentinels.add("192.168.1.101:26379");
        sentinels.add("192.168.1.102:26379");
        sentinels.add("192.168.1.103:26379");
        
        // 创建连接池
        JedisSentinelPool pool = new JedisSentinelPool(
            "mymaster",
            sentinels,
            "YourStrongPassword123!"
        );
        
        // 获取连接
        try (Jedis jedis = pool.getResource()) {
            jedis.set("foo", "bar");
            String value = jedis.get("foo");
            System.out.println(value);
        }
        
        pool.close();
    }
}

6.3 Spring Boot 配置

# application.yml
spring:
  redis:
    sentinel:
      master: mymaster
      nodes:
        - 192.168.1.101:26379
        - 192.168.1.102:26379
        - 192.168.1.103:26379
    password: YourStrongPassword123!
    timeout: 2000ms
    lettuce:
      pool:
        max-active: 8
        max-idle: 8
        min-idle: 0

七、常见问题排查

7.1 Sentinel 无法发现 Master

# 检查网络连通性
ping 192.168.1.101
telnet 192.168.1.101 6379

# 检查防火墙
firewall-cmd --list-ports
iptables -L -n

# 检查 Redis 配置
redis-cli -h 192.168.1.101 -p 6379 -a "YourStrongPassword123!" ping

7.2 故障转移失败

  • 检查 quorum 配置是否合理(3 节点建议设为 2)
  • 检查 Sentinel 日志是否有投票失败信息
  • 确保至少有一个可用的 Slave 节点
  • 检查 masterauth 密码配置是否正确

7.3 数据同步延迟

  • 检查网络带宽和延迟
  • 调整 repl-backlog-size 配置
  • 检查 Slave 节点负载情况

八、优化建议

8.1 生产环境配置

# 增加 Sentinel 节点到 5 个(奇数)
# 调整故障判定时间
sentinel down-after-milliseconds mymaster 10000
sentinel failover-timeout mymaster 180000

# 开启 AOF 持久化
appendonly yes
appendfsync everysec

# 配置内存告警
maxmemory 4gb
maxmemory-policy allkeys-lru

# 配置慢查询日志
slowlog-log-slower-than 10000
slowlog-max-len 128

8.2 监控告警

建议配置以下监控指标:

  • Redis 实例存活状态
  • 主从同步状态
  • 内存使用率
  • 连接数
  • QPS/TPS
  • 慢查询数量

总结

Redis 哨兵模式通过以下机制实现高可用:

  1. 监控:Sentinel 持续监控主从节点状态
  2. 通知:节点故障时通过 API 通知系统管理员
  3. 自动故障转移:Master 故障时自动选举新 Master
  4. 配置中心:客户端可从 Sentinel 获取当前 Master 地址

搭建要点回顾:

  • 至少 3 个节点(1 Master + 2 Slave + 3 Sentinel)
  • Sentinel 的 quorum 设置为 2(3 节点场景)
  • 配置合理的故障判定时间
  • 所有节点配置相同的认证密码
  • 定期测试故障转移确保配置有效

通过本文的完整搭建指南,你应该已经掌握了 Redis 哨兵模式的部署和运维技能。如有问题,欢迎留言讨论!

发表回复

后才能评论