本文详解Redis高可用架构设计,从主从复制到哨兵模式再到Cluster集群的完整实践。
前言
Redis作为最流行的缓存数据库:
- 高性能:10万+ QPS
- 丰富的数据结构
- 简单易用
但单机Redis存在问题:
- 单点故障
- 容量有限
- 无法水平扩展
今天来讲Redis的高可用部署方案。
一、高可用架构选型
1.1 架构对比
| 架构 | 特点 | 适用场景 |
|---|---|---|
| 主从复制 | 读写分离,手动故障转移 | 小规模,读多写少 |
| 哨兵模式 | 自动故障转移 | 中等规模 |
| Cluster集群 | 分片存储,高可用 | 大规模,数据量大 |
1.2 如何选择
数据量 < 10GB,QPS < 5万:主从复制
数据量 < 50GB,需要自动故障转移:哨兵模式
数据量 > 50GB,需要分片:Cluster集群
二、主从复制
2.1 架构图
┌─────────────┐
│ Master │
│ 192.168.1.1 │
│ :6379 │
└──────┬──────┘
│ 同步
┌───┴───┐
↓ ↓
┌──────┐ ┌──────┐
│Slave1│ │Slave2│
│ .2 │ │ .3 │
└──────┘ └──────┘
2.2 Docker部署
yaml
# docker-compose.yml
version: '3.8'
services:
redis-master:
image: redis:7
container_name: redis-master
ports:
- "6379:6379"
volumes:
- ./master/data:/data
- ./master/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
redis-slave1:
image: redis:7
container_name: redis-slave1
ports:
- "6380:6379"
volumes:
- ./slave1/data:/data
- ./slave1/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
depends_on:
- redis-master
redis-slave2:
image: redis:7
container_name: redis-slave2
ports:
- "6381:6379"
volumes:
- ./slave2/data:/data
- ./slave2/redis.conf:/etc/redis/redis.conf
command: redis-server /etc/redis/redis.conf
depends_on:
- redis-master
2.3 配置文件
Master配置:
bash
# master/redis.conf
bind 0.0.0.0
port 6379
requirepass yourpassword
masterauth yourpassword
appendonly yes
Slave配置:
bash
# slave1/redis.conf
bind 0.0.0.0
port 6379
requirepass yourpassword
masterauth yourpassword
replicaof redis-master 6379
appendonly yes
replica-read-only yes
2.4 验证同步
bash
# 连接Master
redis-cli -h 127.0.0.1 -p 6379 -a yourpassword
# 查看复制状态
127.0.0.1:6379> INFO replication
# role:master
# connected_slaves:2
# 写入数据
127.0.0.1:6379> SET test "hello"
# 连接Slave验证
redis-cli -h 127.0.0.1 -p 6380 -a yourpassword
127.0.0.1:6380> GET test
"hello"
三、哨兵模式
3.1 架构图
┌────────────────────────────────┐
│ Sentinel集群 │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ S1 │ │ S2 │ │ S3 │ │
│ └──┬──┘ └──┬──┘ └──┬──┘ │
└─────┼───────┼───────┼────────┘
│ │ │ 监控
┌──────┴───────┴───────┴──────┐
↓ ↓
┌─────────────┐ ┌─────────────┐
│ Master │──同步──────→│ Slave │
└─────────────┘ └─────────────┘
故障转移:Master挂了 → Sentinel投票 → 提升Slave为Master
3.2 部署配置
yaml
# docker-compose.yml 添加哨兵
sentinel1:
image: redis:7
container_name: sentinel1
ports:
- "26379:26379"
volumes:
- ./sentinel1/sentinel.conf:/etc/redis/sentinel.conf
command: redis-sentinel /etc/redis/sentinel.conf
sentinel2:
image: redis:7
container_name: sentinel2
ports:
- "26380:26379"
volumes:
- ./sentinel2/sentinel.conf:/etc/redis/sentinel.conf
command: redis-sentinel /etc/redis/sentinel.conf
sentinel3:
image: redis:7
container_name: sentinel3
ports:
- "26381:26379"
volumes:
- ./sentinel3/sentinel.conf:/etc/redis/sentinel.conf
command: redis-sentinel /etc/redis/sentinel.conf
Sentinel配置:
bash
# sentinel.conf
port 26379
sentinel monitor mymaster redis-master 6379 2
sentinel auth-pass mymaster yourpassword
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
3.3 故障转移测试
bash
# 停止Master
docker stop redis-master
# 查看Sentinel日志
docker logs sentinel1
# +sdown master mymaster 192.168.1.1 6379
# +odown master mymaster 192.168.1.1 6379 #quorum 2/2
# +switch-master mymaster 192.168.1.1 6379 192.168.1.2 6379
# Slave已提升为新Master
3.4 客户端连接
java
// Java连接哨兵
Set<String> sentinels = new HashSet<>();
sentinels.add("192.168.1.1:26379");
sentinels.add("192.168.1.2:26379");
sentinels.add("192.168.1.3:26379");
JedisSentinelPool pool = new JedisSentinelPool(
"mymaster",
sentinels,
config,
"yourpassword"
);
四、Cluster集群
4.1 架构图
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Master1 │ │ Master2 │ │ Master3 │
│ Slot 0-5460│ │Slot 5461- │ │Slot 10923- │
│ │ │ 10922 │ │ 16383 │
└─────┬──────┘ └─────┬──────┘ └─────┬──────┘
│ │ │
↓ ↓ ↓
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Slave1 │ │ Slave2 │ │ Slave3 │
└────────────┘ └────────────┘ └────────────┘
数据按Key的CRC16值分配到16384个槽位
每个Master负责一部分槽位
4.2 部署
bash
# 创建6个节点(3主3从)
for port in 7001 7002 7003 7004 7005 7006; do
mkdir -p cluster/${port}
cat > cluster/${port}/redis.conf << EOF
port ${port}
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
requirepass yourpassword
masterauth yourpassword
EOF
done
# 启动节点
for port in 7001 7002 7003 7004 7005 7006; do
docker run -d --name redis-${port} \
-p ${port}:${port} -p 1${port}:1${port} \
-v $(pwd)/cluster/${port}:/data \
redis:7 redis-server /data/redis.conf
done
# 创建集群
redis-cli --cluster create \
192.168.1.1:7001 192.168.1.1:7002 192.168.1.1:7003 \
192.168.1.1:7004 192.168.1.1:7005 192.168.1.1:7006 \
--cluster-replicas 1 -a yourpassword
4.3 集群操作
bash
# 连接集群(-c表示集群模式)
redis-cli -c -p 7001 -a yourpassword
# 查看集群状态
127.0.0.1:7001> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_known_nodes:6
# 查看节点信息
127.0.0.1:7001> CLUSTER NODES
# 设置Key(自动路由)
127.0.0.1:7001> SET user:1 "test"
-> Redirected to slot [8106] located at 192.168.1.1:7002
OK
4.4 扩容
bash
# 添加新节点
redis-cli --cluster add-node 192.168.1.1:7007 192.168.1.1:7001 -a yourpassword
# 重新分配槽位
redis-cli --cluster reshard 192.168.1.1:7001 -a yourpassword
# 添加从节点
redis-cli --cluster add-node 192.168.1.1:7008 192.168.1.1:7007 \
--cluster-slave --cluster-master-id <master-id> -a yourpassword
五、跨机房/多站点部署
5.1 场景挑战
需求:
- 总部机房:3台服务器
- 分部机房:3台服务器
- 需要搭建6节点Cluster
挑战:
- 两个机房网络不通
- Redis Cluster需要节点互通
5.2 解决方案
使用组网软件(如星空组网)打通网络:
组网后的部署:
┌─────────────────────────────────────────────────────────┐
│ 组网虚拟局域网 │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ 总部机房 │ │ 分部机房 │ │
│ │ │ │ │ │
│ │ Master1(10.10.0.1) │ Master2(10.10.0.4)│ │
│ │ Master3(10.10.0.2) │ Slave1 (10.10.0.5)│ │
│ │ Slave2 (10.10.0.3) │ Slave3 (10.10.0.6)│ │
│ │ │ │ │ │
│ └──────────────────┘ └──────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
配置:
bash
# 各节点配置中使用组网IP
# 节点1(总部)
cluster-announce-ip 10.10.0.1
cluster-announce-port 7001
cluster-announce-bus-port 17001
# 节点4(分部)
cluster-announce-ip 10.10.0.4
cluster-announce-port 7001
cluster-announce-bus-port 17001
# 创建集群时使用组网IP
redis-cli --cluster create \
10.10.0.1:7001 10.10.0.2:7001 10.10.0.3:7001 \
10.10.0.4:7001 10.10.0.5:7001 10.10.0.6:7001 \
--cluster-replicas 1 -a yourpassword
效果:
- 跨机房节点通过组网IP互通
- Cluster正常工作
- 加密传输,安全可靠
5.3 跨机房容灾策略
主从分布策略:
- 每个Master的Slave部署在不同机房
- 机房故障时,另一机房的Slave可提升为Master
┌──────────────┐ ┌──────────────┐
│ 总部 │ │ 分部 │
│ Master1 ←───────同步──→ Slave1 │
│ Master2 ←───────同步──→ Slave2 │
│ Slave3 ←───────同步──→ Master3 │
└──────────────┘ └──────────────┘
六、运维管理
6.1 监控指标
bash
# 关键指标
redis-cli INFO | grep -E "connected_clients|used_memory|hit_rate|ops_per_sec"
# 监控脚本
#!/bin/bash
HOSTS=("10.10.0.1:6379" "10.10.0.2:6379" "10.10.0.3:6379")
for host in ${HOSTS[@]}; do
echo "=== $host ==="
redis-cli -h ${host%:*} -p ${host#*:} -a yourpassword INFO | \
grep -E "connected_clients|used_memory_human|keyspace_hits"
done
6.2 数据备份
bash
# RDB备份
redis-cli -a yourpassword BGSAVE
# 备份文件位置
/data/dump.rdb
# 定时备份脚本
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
redis-cli -a yourpassword BGSAVE
sleep 5
cp /data/dump.rdb /backup/redis_${DATE}.rdb
6.3 性能优化
bash
# redis.conf优化
# 内存策略
maxmemory 4gb
maxmemory-policy allkeys-lru
# 持久化优化(写入性能)
appendfsync everysec
# 连接优化
tcp-backlog 511
timeout 300
tcp-keepalive 300
# 慢查询日志
slowlog-log-slower-than 10000
slowlog-max-len 128
6.4 常用命令
bash
# 查看大Key
redis-cli -a yourpassword --bigkeys
# 查看内存分析
redis-cli -a yourpassword --memkeys
# 慢查询
redis-cli -a yourpassword SLOWLOG GET 10
# 客户端列表
redis-cli -a yourpassword CLIENT LIST
七、常见问题
7.1 主从同步延迟
bash
# 查看延迟
redis-cli -a yourpassword INFO replication | grep lag
# 解决方案
# 1. 增加repl-backlog-size
repl-backlog-size 256mb
# 2. 网络优化(使用组网降低延迟)
7.2 Cluster MOVED错误
bash
# 客户端需要使用集群模式
# Java: JedisCluster
# Python: redis-py-cluster
JedisCluster cluster = new JedisCluster(nodes, config);
7.3 内存不足
bash
# 查看内存使用
redis-cli -a yourpassword INFO memory
# 清理过期Key
redis-cli -a yourpassword --scan --pattern "*" | head -1000 | xargs redis-cli DEL
# 设置过期时间
EXPIRE key 3600
八、总结
Redis高可用部署要点:
| 架构 | 节点数 | 自动故障转移 | 分片 |
|---|---|---|---|
| 主从复制 | 2+ | ❌ | ❌ |
| 哨兵模式 | 5+(含哨兵) | ✅ | ❌ |
| Cluster | 6+ | ✅ | ✅ |
我的建议:
- 小项目:主从复制够用
- 一般项目:哨兵模式
- 大数据量:Cluster集群
- 跨机房:组网 + Cluster
关键配置:
1. 密码认证
2. 持久化策略
3. 内存限制
4. 监控告警
参考资料
- Redis官方文档:https://redis.io/docs/
- Redis Cluster扩展指南:https://redis.io/learn/operate/redis-at-scale/scalability/
- Redis集群API文档:https://redis.io/docs/latest/operate/rs/clusters/
💡 建议:生产环境至少使用哨兵模式,避免单点故障。定期备份数据,监控内存使用。