Redis单实例部署存在单点故障风险,宕机即全站缓存失效。Redis提供两种高可用方案:Sentinel哨兵模式适合中小规模,主从复制+自动故障转移;Cluster分片集群适合大规模数据,自动分片+多主多从。哨兵模式不支持水平扩展,数据量受单机内存限制;Cluster模式通过分片突破单机内存限制,支持线性扩展。本文分别搭建两种集群,覆盖配置部署、故障切换、数据迁移等完整流程。
Redis高可用架构选型分析
Sentinel哨兵模式:一主多从,Sentinel节点监控主从状态,主节点故障时自动选举新主。所有数据在主节点上,通过复制同步到从节点。优点是配置简单、客户端兼容性好;缺点是不支持水平扩展,写入性能受限于单节点。
Cluster分片集群:多个主节点组成集群,数据按slot分片存储,每个主节点负责一部分slot。主节点故障时,对应的从节点接管。优点是水平扩展、写入吞吐量随节点数线性增长;缺点是配置复杂、跨slot操作受限(多key操作需要hash tag)。
选型参考:数据量小于50GB、QPS小于10万,选Sentinel;数据量超过50GB或需要更高写入吞吐量,选Cluster。两者可以组合使用——Cluster集群的每个分片主从之间使用Sentinel监控,但通常Cluster自身的故障转移机制已足够,不需要额外部署Sentinel。
哨兵模式部署配置
部署规划:1主2从3哨兵,共6个Redis进程。主节点6379,从节点6380/6381,哨兵26379/26380/26381。
# 主节点 redis-6379.conf
port 6379
bind 0.0.0.0
protected-mode yes
daemonize yes
pidfile /var/run/redis-6379.pid
logfile /var/log/redis/redis-6379.log
dir /data/redis/6379
# 认证配置
requirepass "RedisProd@2026"
masterauth "RedisProd@2026"
# 持久化配置
appendonly yes
appendfsync everysec
save 900 1
save 300 10
save 60 10000
# 内存策略
maxmemory 8gb
maxmemory-policy allkeys-lru
# 从节点1 redis-6380.conf
port 6380
bind 0.0.0.0
daemonize yes
pidfile /var/run/redis-6380.pid
logfile /var/log/redis/redis-6380.log
dir /data/redis/6380
requirepass "RedisProd@2026"
masterauth "RedisProd@2026"
# 指定主节点地址
replicaof 127.0.0.1 6379
# 从节点只读
replica-read-only yes
# 复制积压缓冲区(部分重同步优化)
repl-backlog-size 64mb
repl-backlog-ttl 3600
appendonly yes
appendfsync everysec
maxmemory 8gb
maxmemory-policy allkeys-lru
# 哨兵1 sentinel-26379.conf
port 26379
bind 0.0.0.0
daemonize yes
pidfile /var/run/sentinel-26379.pid
logfile /var/log/redis/sentinel-26379.log
dir /data/redis/sentinel-26379
# 监控主节点,2个哨兵同意才判定主节点下线(quorum=2)
sentinel monitor mymaster 127.0.0.1 6379 2
# 主节点认证密码
sentinel auth-pass mymaster "RedisProd@2026"
# 主观下线判定:30秒无响应
sentinel down-after-milliseconds mymaster 30000
# 故障转移超时:180秒
sentinel failover-timeout mymaster 180000
# 故障转移时同时进行同步的从节点数量
sentinel parallel-syncs mymaster 1
启动顺序:主节点到从节点到哨兵:
# 启动主节点
redis-server /etc/redis/redis-6379.conf
# 启动从节点
redis-server /etc/redis/redis-6380.conf
redis-server /etc/redis/redis-6381.conf
# 启动哨兵
redis-sentinel /etc/redis/sentinel-26379.conf
redis-sentinel /etc/redis/sentinel-26380.conf
redis-sentinel /etc/redis/sentinel-26381.conf
# 验证主从复制状态
redis-cli -a "RedisProd@2026" -p 6379 info replication
# 预期输出:role:master, connected_slaves:2
# 验证哨兵状态
redis-cli -p 26379 sentinel master mymaster
# 预期输出:num-slaves:2, num-other-sentinels:2
Redis Cluster分片集群搭建
部署规划:6个节点(3主3从),端口7000-7005。Cluster需要至少3个主节点才能正常工作。
# 以7000端口为例,其他5个节点配置类似,修改port和dir即可
# redis-7000.conf
port 7000
bind 0.0.0.0
daemonize yes
cluster-enabled yes # 开启Cluster模式
cluster-config-file nodes-7000.conf # 集群配置文件(自动生成)
cluster-node-timeout 15000 # 节点超时15秒
cluster-announce-ip 192.168.1.100 # 对外宣布的IP
cluster-announce-port 7000
cluster-announce-bus-port 17000 # 集群总线端口
requirepass "RedisCluster@2026"
masterauth "RedisCluster@2026"
appendonly yes
appendfsync everysec
maxmemory 16gb
maxmemory-policy allkeys-lru
# 慢查询日志
slowlog-log-slower-than 10000 # 记录执行超过10ms的命令
slowlog-max-len 128
批量创建6个节点的配置并启动:
#!/bin/bash
# create_cluster.sh
for port in 7000 7001 7002 7003 7004 7005; do
mkdir -p /data/redis/${port}
cat > /etc/redis/redis-${port}.conf << EOF
port ${port}
bind 0.0.0.0
daemonize yes
cluster-enabled yes
cluster-config-file nodes-${port}.conf
cluster-node-timeout 15000
requirepass "RedisCluster@2026"
masterauth "RedisCluster@2026"
appendonly yes
appendfsync everysec
dir /data/redis/${port}
maxmemory 16gb
maxmemory-policy allkeys-lru
EOF
redis-server /etc/redis/redis-${port}.conf
echo "Started Redis on port ${port}"
done
使用redis-cli创建集群:
# 创建3主3从集群,自动分配主从关系
redis-cli --cluster create 192.168.1.100:7000 192.168.1.100:7001 192.168.1.100:7002 192.168.1.100:7003 192.168.1.100:7004 192.168.1.100:7005 --cluster-replicas 1 -a "RedisCluster@2026"
# 输出:
# >>> Performing hash slots allocation on 6 nodes...
# Master[0] -> 192.168.1.100:7000 (slots 0-5460)
# Master[1] -> 192.168.1.100:7001 (slots 5461-10922)
# Master[2] -> 192.168.1.100:7002 (slots 10923-16383)
# Master[0] replica -> 192.168.1.100:7003
# Master[1] replica -> 192.168.1.100:7004
# Master[2] replica -> 192.168.1.100:7005
# 验证集群状态
redis-cli -p 7000 -a "RedisCluster@2026" cluster info
# cluster_state:ok, cluster_slots_assigned:16384
# 查看节点信息
redis-cli -p 7000 -a "RedisCluster@2026" cluster nodes
集群数据迁移与扩容
Cluster扩容需要添加新节点并迁移slot。以新增7006和7007节点为例:
# 1. 启动新节点(配置同上,端口改为7006/7007)
redis-server /etc/redis/redis-7006.conf
redis-server /etc/redis/redis-7007.conf
# 2. 将7006加入集群作为主节点
redis-cli --cluster add-node 192.168.1.100:7006 192.168.1.100:7000 -a "RedisCluster@2026"
# 3. 将7007加入集群作为7006的从节点
redis-cli --cluster add-node 192.168.1.100:7007 192.168.1.100:7000 --cluster-slave --cluster-master-id <7006的node_id> -a "RedisCluster@2026"
# 4. 重新分配slot,从现有主节点迁移部分slot到7006
redis-cli --cluster reshard 192.168.1.100:7000 -a "RedisCluster@2026" --cluster-from all --cluster-to <7006的node_id> --cluster-slots 4096 --cluster-yes
# 迁移4096个slot到新节点,每个现有主节点各迁出约1365个slot
# 迁移过程中集群正常服务,单个key的迁移是原子操作
高可用故障切换测试
哨兵模式故障切换测试:
# 模拟主节点宕机
redis-cli -a "RedisProd@2026" -p 6379 shutdown nosave
# 观察哨兵日志
tail -f /var/log/redis/sentinel-26379.log
# 预期流程:
# +sdown master mymaster 127.0.0.1 6379 (主观下线)
# +odown master mymaster 127.0.0.1 6379 #quorum 2/2 (客观下线)
# +new-epoch 1
# +try-failover master mymaster 127.0.0.1 6379 (开始故障转移)
# +selected-slave 127.0.0.1:6380 (选举6380为新主)
# +failover-state-send-slaveof-noone (命令新主停止复制)
# +failover-state-flush-config (刷新配置)
# +failover-end master mymaster 127.0.0.1 6379
# +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380 (切换完成)
# 验证新主节点
redis-cli -a "RedisProd@2026" -p 6380 info replication
# role:master, connected_slaves:1
# 恢复旧主节点,它将自动成为新主的从节点
redis-server /etc/redis/redis-6379.conf
redis-cli -a "RedisProd@2026" -p 6380 info replication
# connected_slaves:2
Cluster模式故障切换测试:
# 模拟7000主节点宕机
redis-cli -p 7000 -a "RedisCluster@2026" shutdown nosave
# 等待15秒(cluster-node-timeout),集群检测到节点故障
# 7003(7000的从节点)自动提升为主节点
# 查看集群状态
redis-cli -p 7001 -a "RedisCluster@2026" cluster nodes
# 7000显示fail状态,7003变为master
# 验证数据完整性
redis-cli -c -p 7001 -a "RedisCluster@2026" dbsize
# slot数据正常,无丢失
# 恢复7000节点,它将作为7003的从节点重新加入
redis-server /etc/redis/redis-7000.conf
# 等待自动同步完成
redis-cli -p 7003 -a "RedisCluster@2026" cluster nodes
# 7000显示slave状态
客户端连接Cluster需要使用支持Cluster协议的客户端。Java环境使用Jedis或Lettuce,Spring Boot中配置RedisTemplate连接Cluster:
# application.yml
spring:
data:
redis:
cluster:
nodes: 192.168.1.100:7000,192.168.1.100:7001,192.168.1.100:7002
max-redirects: 3 # MOVED重定向最大次数
password: "RedisCluster@2026"
lettuce:
pool:
max-active: 100
max-idle: 20
min-idle: 5
cluster:
refresh:
adaptive: true # 自适应刷新拓扑
period: 30s # 定期刷新间隔
adaptive刷新模式让客户端在遇到MOVED/ASK错误时自动更新slot映射表,定期刷新确保客户端在节点扩缩容后及时感知拓扑变化。max-redirects设置为3,避免在集群不稳定时客户端陷入无限重定向循环。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/redis-gao-ke-yong-ji-qun-da-jian-shi-zhan-shao-bing-mo-shi/