Redis哨兵搭建教程

# Redis哨兵搭建教程

Redis哨兵(Sentinel)是Redis的高可用解决方案,能够自动监控、通知和故障转移。

## 前言

Redis哨兵是Redis官方提供的高可用解决方案,能够自动监控主从节点状态,在主节点故障时自动进行故障转移。本文将详细介绍如何搭建Redis哨兵集群。

## 环境准备

### 服务器规划

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

| 服务器IP | Redis端口 | 哨兵端口 | 角色 |
|----------|-----------|----------|------|
| 192.168.1.10 | 6379 | 26379 | Master + Sentinel1 |
| 192.168.1.11 | 6379 | 26379 | Slave1 + Sentinel2 |
| 192.168.1.12 | 6379 | 26379 | Slave2 + Sentinel3 |

### 系统要求

- 操作系统:CentOS 7+ 或 Ubuntu 18.04+
- Redis版本:5.0+(建议使用6.0+)
- 内存:至少2GB RAM
- 网络:服务器之间网络互通

## 安装Redis

### 1. 安装依赖

```bash
# CentOS
yum install -y gcc make tcl

# Ubuntu
apt-get install -y build-essential tcl
```

### 2. 下载并编译Redis

```bash
cd /usr/local/src
wget http://download.redis.io/releases/redis-6.2.6.tar.gz
tar xzf redis-6.2.6.tar.gz
cd redis-6.2.6
make
make install
```

### 3. 创建目录结构

```bash
mkdir -p /etc/redis
mkdir -p /var/log/redis
mkdir -p /var/lib/redis
mkdir -p /var/run/redis
```

## 配置Redis主从复制

### Master配置文件

在192.168.1.10上创建配置文件 `/etc/redis/redis.conf`:

```bash
bind 0.0.0.0
port 6379
daemonize yes
pidfile /var/run/redis/redis.pid
logfile /var/log/redis/redis.log
dir /var/lib/redis
requirepass "your_password"
masterauth "your_password"
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
```

### Slave配置文件

在192.168.1.11和192.168.1.12上创建配置文件 `/etc/redis/redis.conf`:

```bash
bind 0.0.0.0
port 6379
daemonize yes
pidfile /var/run/redis/redis.pid
logfile /var/log/redis/redis.log
dir /var/lib/redis
replicaof 192.168.1.10 6379
masterauth "your_password"
requirepass "your_password"
replica-read-only yes
replica-priority 100
save 900 1
save 300 10
save 60 10000
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
```

### 启动Redis实例

```bash
# 在所有节点上执行
redis-server /etc/redis/redis.conf

# 检查状态
redis-cli -h 192.168.1.10 -p 6379 -a "your_password" ping
redis-cli -h 192.168.1.11 -p 6379 -a "your_password" ping
redis-cli -h 192.168.1.12 -p 6379 -a "your_password" ping
```

### 验证主从复制

```bash
# 在Master上查看复制信息
redis-cli -h 192.168.1.10 -p 6379 -a "your_password" info replication

# 在Slave上查看复制信息
redis-cli -h 192.168.1.11 -p 6379 -a "your_password" info replication
```

## 配置Redis哨兵

### 哨兵配置文件

在所有3台服务器上创建哨兵配置文件 `/etc/redis/sentinel.conf`:

```bash
port 26379
daemonize yes
pidfile /var/run/redis/sentinel.pid
logfile /var/log/redis/sentinel.log
dir /var/lib/redis

# 监控主节点,quorum为2表示2个哨兵认为主节点下线才进行故障转移
sentinel monitor mymaster 192.168.1.10 6379 2

# 主节点密码
sentinel auth-pass mymaster your_password

# 30秒无响应认为下线
sentinel down-after-milliseconds mymaster 30000

# 故障转移超时时间180秒
sentinel failover-timeout mymaster 180000

# 故障转移时同时同步的从节点数量
sentinel parallel-syncs mymaster 1
```

### 启动哨兵

```bash
# 在所有节点上执行
redis-sentinel /etc/redis/sentinel.conf

# 检查哨兵状态
redis-cli -p 26379 info sentinel
```

### 验证哨兵集群

```bash
# 查看监控的主节点
redis-cli -p 26379 sentinel masters

# 查看从节点信息
redis-cli -p 26379 sentinel slaves mymaster

# 查看其他哨兵信息
redis-cli -p 26379 sentinel sentinels mymaster
```

## 故障转移测试

### 模拟Master故障

```bash
# 停止Master节点
redis-cli -h 192.168.1.10 -p 6379 -a "your_password" shutdown nosave
```

### 观察故障转移过程

```bash
# 实时查看哨兵日志
tail -f /var/log/redis/sentinel.log
```

哨兵会自动选择一个Slave升级为Master,整个过程自动完成。

### 验证新的Master

```bash
# 查看新的Master信息
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster

# 连接新的Master
redis-cli -h <新Master的IP> -p 6379 -a "your_password" info replication
```

### 恢复原Master

```bash
# 重启原Master节点
redis-server /etc/redis/redis.conf

# 原Master会自动成为新Master的从节点
```

## 客户端连接

### Python客户端

```python
from redis.sentinel import Sentinel

# 配置哨兵地址
sentinel = Sentinel([
('192.168.1.10', 26379),
('192.168.1.11', 26379),
('192.168.1.12', 26379)
], socket_timeout=0.1)

# 获取主节点连接
master = sentinel.master_for('mymaster', password='your_password')
master.set('key', 'value')

# 获取从节点连接
slave = sentinel.slave_for('mymaster', password='your_password')
value = slave.get('key')
print(value)
```

### Java客户端(Jedis)

```java
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;
import java.util.HashSet;
import java.util.Set;

public class RedisSentinelExample {
public static void main(String[] args) {
// 哨兵地址
Set sentinels = new HashSet<>();
sentinels.add("192.168.1.10:26379");
sentinels.add("192.168.1.11:26379");
sentinels.add("192.168.1.12:26379");

// 创建连接池
JedisSentinelPool pool = new JedisSentinelPool(
"mymaster",
sentinels,
"your_password"
);

// 获取连接
Jedis jedis = null;
try {
jedis = pool.getResource();
jedis.set("key", "value");
String value = jedis.get("key");
System.out.println(value);
} finally {
if (jedis != null) {
jedis.close();
}
pool.close();
}
}
}
```

### Go客户端

```go
package main

import (
"fmt"
"github.com/go-redis/redis/v8"
"context"
)

func main() {
// 创建哨兵客户端
rdb := redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: "mymaster",
SentinelAddrs: []string{
"192.168.1.10:26379",
"192.168.1.11:26379",
"192.168.1.12:26379",
},
Password: "your_password",
})

ctx := context.Background()

// 写操作
err := rdb.Set(ctx, "key", "value", 0).Err()
if err != nil {
panic(err)
}

// 读操作
val, err := rdb.Get(ctx, "key").Result()
if err != nil {
panic(err)
}
fmt.Println(val)
}
```

## 监控与维护

### 查看哨兵状态

```bash
# 查看哨兵信息
redis-cli -p 26379 info sentinel

# 查看主节点信息
redis-cli -p 26379 sentinel masters

# 查看从节点信息
redis-cli -p 26379 sentinel slaves mymaster
```

### 查看Redis性能

```bash
# 查看统计信息
redis-cli -h 192.168.1.10 -p 6379 -a "your_password" info stats

# 查看内存使用
redis-cli -h 192.168.1.10 -p 6379 -a "your_password" info memory

# 查看持久化状态
redis-cli -h 192.168.1.10 -p 6379 -a "your_password" info persistence
```

### 日志监控

```bash
# 实时查看哨兵日志
tail -f /var/log/redis/sentinel.log

# 实时查看Redis日志
tail -f /var/log/redis/redis.log
```

### 备份策略

```bash
# 定期备份RDB文件
cp /var/lib/redis/dump.rdb /backup/redis/dump_$(date +%Y%m%d).rdb

# 定期备份AOF文件
cp /var/lib/redis/appendonly.aof /backup/redis/appendonly_$(date +%Y%m%d).aof
```

## 常见问题

### 哨兵无法启动

```bash
# 检查配置文件语法
redis-sentinel /etc/redis/sentinel.conf --test-memory 1

# 检查端口是否被占用
netstat -tlnp | grep 26379

# 检查日志
cat /var/log/redis/sentinel.log
```

### 故障转移失败

```bash
# 检查quorum配置
redis-cli -p 26379 sentinel get-master-addr-by-name mymaster

# 检查从节点状态
redis-cli -h 192.168.1.11 -p 6379 info replication

# 检查网络连通性
ping 192.168.1.10
ping 192.168.1.11
ping 192.168.1.12
```

### 主从同步延迟

```bash
# 优化复制缓冲区大小
# 在redis.conf中设置:
repl-backlog-size 10mb
repl-backlog-ttl 3600
```

### 哨兵脑裂

```bash
# 增加quorum数量
sentinel monitor mymaster 192.168.1.10 6379 3

# 增加故障转移超时时间
sentinel failover-timeout mymaster 300000
```

## 最佳实践

### 部署建议

1. 哨兵数量至少3个,建议5个(奇数)
2. 哨兵应该部署在不同的物理服务器上
3. Redis和哨兵应该在同一内网
4. 每个哨兵至少需要512MB内存

### 安全建议

1. 为所有Redis实例设置强密码
2. 使用防火墙限制访问
3. 生产环境建议启用SSL加密
4. 定期更新Redis版本

### 性能优化

1. 根据业务需求选择RDB或AOF持久化
2. 合理设置maxmemory和淘汰策略
3. 调整TCP参数优化网络性能
4. 建立完善的监控告警体系

## 总结

Redis哨兵是成熟的高可用解决方案,能够有效保障Redis服务的稳定性。通过本文的介绍,你应该能够:

1. 理解Redis哨兵的架构和工作原理
2. 成功搭建Redis主从复制集群
3. 配置和部署Redis哨兵
4. 进行故障转移测试
5. 集成客户端连接哨兵
6. 进行监控和维护
7. 解决常见问题

记住:在生产环境中,务必做好充分的测试和监控,确保系统的高可用性!

发表回复

后才能评论