本文详解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部署
# docker-compose.ymlversion:'3.8'services:redis-master:image:redis:7container_name:redis-masterports:-"6379:6379"volumes:-./master/data:/data-./master/redis.conf:/etc/redis/redis.confcommand:redis-server /etc/redis/redis.confredis-slave1:image:redis:7container_name:redis-slave1ports:-"6380:6379"volumes:-./slave1/data:/data-./slave1/redis.conf:/etc/redis/redis.confcommand:redis-server /etc/redis/redis.confdepends_on:-redis-masterredis-slave2:image:redis:7container_name:redis-slave2ports:-"6381:6379"volumes:-./slave2/data:/data-./slave2/redis.conf:/etc/redis/redis.confcommand:redis-server /etc/redis/redis.confdepends_on:-redis-master2.3 配置文件
Master配置:
# master/redis.confbind0.0.0.0 port6379requirepass yourpassword masterauth yourpassword appendonlyyesSlave配置:
# slave1/redis.confbind0.0.0.0 port6379requirepass yourpassword masterauth yourpassword replicaof redis-master6379appendonlyyesreplica-read-onlyyes2.4 验证同步
# 连接Masterredis-cli -h127.0.0.1 -p6379-a yourpassword# 查看复制状态127.0.0.1:6379>INFO replication# role:master# connected_slaves:2# 写入数据127.0.0.1:6379>SETtest"hello"# 连接Slave验证redis-cli -h127.0.0.1 -p6380-a yourpassword127.0.0.1:6380>GETtest"hello"三、哨兵模式
3.1 架构图
┌────────────────────────────────┐ │ Sentinel集群 │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ │ │ S1 │ │ S2 │ │ S3 │ │ │ └──┬──┘ └──┬──┘ └──┬──┘ │ └─────┼───────┼───────┼────────┘ │ │ │ 监控 ┌──────┴───────┴───────┴──────┐ ↓ ↓ ┌─────────────┐ ┌─────────────┐ │ Master │──同步──────→│ Slave │ └─────────────┘ └─────────────┘ 故障转移:Master挂了 → Sentinel投票 → 提升Slave为Master3.2 部署配置
# docker-compose.yml 添加哨兵sentinel1:image:redis:7container_name:sentinel1ports:-"26379:26379"volumes:-./sentinel1/sentinel.conf:/etc/redis/sentinel.confcommand:redis-sentinel /etc/redis/sentinel.confsentinel2:image:redis:7container_name:sentinel2ports:-"26380:26379"volumes:-./sentinel2/sentinel.conf:/etc/redis/sentinel.confcommand:redis-sentinel /etc/redis/sentinel.confsentinel3:image:redis:7container_name:sentinel3ports:-"26381:26379"volumes:-./sentinel3/sentinel.conf:/etc/redis/sentinel.confcommand:redis-sentinel /etc/redis/sentinel.confSentinel配置:
# sentinel.confport26379sentinel monitor mymaster redis-master63792sentinel auth-pass mymaster yourpassword sentinel down-after-milliseconds mymaster5000sentinel failover-timeout mymaster60000sentinel parallel-syncs mymaster13.3 故障转移测试
# 停止Masterdocker 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已提升为新Master3.4 客户端连接
// Java连接哨兵Set<String>sentinels=newHashSet<>();sentinels.add("192.168.1.1:26379");sentinels.add("192.168.1.2:26379");sentinels.add("192.168.1.3:26379");JedisSentinelPoolpool=newJedisSentinelPool("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 部署
# 创建6个节点(3主3从)forportin700170027003700470057006;domkdir-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 EOFdone# 启动节点forportin700170027003700470057006;dodocker run -d --name redis-${port}\-p${port}:${port}-p1${port}:1${port}\-v$(pwd)/cluster/${port}:/data\redis:7 redis-server /data/redis.confdone# 创建集群redis-cli --cluster create\192.168.1.1:7001192.168.1.1:7002192.168.1.1:7003\192.168.1.1:7004192.168.1.1:7005192.168.1.1:7006\--cluster-replicas1-a yourpassword4.3 集群操作
# 连接集群(-c表示集群模式)redis-cli -c -p7001-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 at192.168.1.1:7002 OK4.4 扩容
# 添加新节点redis-cli --cluster add-node192.168.1.1:7007192.168.1.1:7001 -a yourpassword# 重新分配槽位redis-cli --cluster reshard192.168.1.1:7001 -a yourpassword# 添加从节点redis-cli --cluster add-node192.168.1.1:7008192.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)│ │ │ │ │ │ │ │ │ └──────────────────┘ └──────────────────┘ │ │ │ └─────────────────────────────────────────────────────────┘配置:
# 各节点配置中使用组网IP# 节点1(总部)cluster-announce-ip10.10.0.1 cluster-announce-port7001cluster-announce-bus-port17001# 节点4(分部)cluster-announce-ip10.10.0.4 cluster-announce-port7001cluster-announce-bus-port17001# 创建集群时使用组网IPredis-cli --cluster create\10.10.0.1:700110.10.0.2:700110.10.0.3:7001\10.10.0.4:700110.10.0.5:700110.10.0.6:7001\--cluster-replicas1-a yourpassword效果:
- 跨机房节点通过组网IP互通
- Cluster正常工作
- 加密传输,安全可靠
5.3 跨机房容灾策略
主从分布策略: - 每个Master的Slave部署在不同机房 - 机房故障时,另一机房的Slave可提升为Master ┌──────────────┐ ┌──────────────┐ │ 总部 │ │ 分部 │ │ Master1 ←───────同步──→ Slave1 │ │ Master2 ←───────同步──→ Slave2 │ │ Slave3 ←───────同步──→ Master3 │ └──────────────┘ └──────────────┘六、运维管理
6.1 监控指标
# 关键指标redis-cli INFO|grep-E"connected_clients|used_memory|hit_rate|ops_per_sec"# 监控脚本#!/bin/bashHOSTS=("10.10.0.1:6379""10.10.0.2:6379""10.10.0.3:6379")forhostin${HOSTS[@]};doecho"===$host==="redis-cli -h${host%:*}-p${host#*:}-a yourpassword INFO|\grep-E"connected_clients|used_memory_human|keyspace_hits"done6.2 数据备份
# RDB备份redis-cli -a yourpassword BGSAVE# 备份文件位置/data/dump.rdb# 定时备份脚本#!/bin/bashDATE=$(date+%Y%m%d_%H%M%S)redis-cli -a yourpassword BGSAVEsleep5cp/data/dump.rdb /backup/redis_${DATE}.rdb6.3 性能优化
# redis.conf优化# 内存策略maxmemory 4gb maxmemory-policy allkeys-lru# 持久化优化(写入性能)appendfsync everysec# 连接优化tcp-backlog511timeout300tcp-keepalive300# 慢查询日志slowlog-log-slower-than10000slowlog-max-len1286.4 常用命令
# 查看大Keyredis-cli -a yourpassword --bigkeys# 查看内存分析redis-cli -a yourpassword --memkeys# 慢查询redis-cli -a yourpassword SLOWLOG GET10# 客户端列表redis-cli -a yourpassword CLIENT LIST七、常见问题
7.1 主从同步延迟
# 查看延迟redis-cli -a yourpassword INFO replication|greplag# 解决方案# 1. 增加repl-backlog-sizerepl-backlog-size 256mb# 2. 网络优化(使用组网降低延迟)7.2 Cluster MOVED错误
# 客户端需要使用集群模式# Java: JedisCluster# Python: redis-py-clusterJedisCluster cluster=new JedisCluster(nodes, config);7.3 内存不足
# 查看内存使用redis-cli -a yourpassword INFO memory# 清理过期Keyredis-cli -a yourpassword --scan --pattern"*"|head-1000|xargsredis-cli DEL# 设置过期时间EXPIRE key3600八、总结
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/
💡建议:生产环境至少使用哨兵模式,避免单点故障。定期备份数据,监控内存使用。