Redis高可用架构选型与适用场景
Redis高可用方案主要有Sentinel哨兵模式和Cluster集群模式两种。Sentinel适用于单主单从(或多从)架构,通过哨兵进程监控主节点状态并在故障时自动切换从节点为主节点,适合数据量不大但要求高可用的场景。Cluster模式通过分片将数据分布在多个节点上,每个节点负责一部分slot,支持水平扩展和自动故障转移,适合大数据量和高吞吐场景。
两者的核心区别:Sentinel模式所有节点存储完整数据副本,容量受限于单机内存,但客户端连接简单;Cluster模式数据分散存储,总容量为各节点内存之和,但需要客户端支持Cluster协议,跨slot操作受限。在实际选型中,数据量预估超过单机内存60%时应选择Cluster模式。
Redis Cluster集群部署配置
以六节点Cluster集群(三主三从)为例,在单机环境使用不同端口模拟多节点:
# 创建6个Redis实例的配置文件
# redis-cluster-7000.conf ~ redis-cluster-7005.conf
# redis-cluster-7000.conf
port 7000
bind 0.0.0.0
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
appendonly yes
appendfilename "appendonly-7000.aof"
dir /data/redis/7000
logfile /var/log/redis/redis-7000.log
daemonize yes
maxmemory 4gb
maxmemory-policy allkeys-lru
# 复制配置文件并修改端口
for port in 7001 7002 7003 7004 7005; do
sed "s/7000/$port/g" redis-cluster-7000.conf > redis-cluster-$port.conf
mkdir -p /data/redis/$port
done
# 启动所有Redis实例
for port in 7000 7001 7002 7003 7004 7005; do
redis-server /etc/redis/redis-cluster-$port.conf
done
# 检查进程
ps aux | grep redis-server | grep cluster
使用redis-cli创建集群,指定主从关系:
# 创建Cluster集群,3主3从
# --cluster-replicas 1 表示每个主节点配1个从节点
redis-cli --cluster create \
127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
# 集群创建后验证状态
redis-cli -p 7000 cluster info
# 输出:
# cluster_state:ok
# cluster_slots_assigned:16384
# cluster_slots_ok:16384
# cluster_known_nodes:6
# cluster_size:3
# 查看集群节点信息
redis-cli -p 7000 cluster nodes
# 输出示例:
# 7000节点 - master - slots 0-5460
# 7001节点 - master - slots 5461-10922
# 7002节点 - master - slots 10923-16383
# 7003节点 - slave - 7000的从节点
# 7004节点 - slave - 7001的从节点
# 7005节点 - slave - 7002的从节点
Redis Cluster数据分片与slot操作
Redis Cluster将16384个slot分配到各主节点,每个key通过CRC16算法计算后取模映射到对应slot。跨slot操作会返回MOVED错误:
# 查看key所在的slot
redis-cli -p 7000 cluster keyslot mykey
# 输出: (integer) 14000
# 直接操作对应slot的节点
redis-cli -p 7000 set mykey "hello"
# 如果key不在7000节点,返回MOVED重定向
# (error) MOVED 14000 127.0.0.1:7002
# 使用-c参数自动重定向
redis-cli -c -p 7000 set mykey "hello"
# OK (自动重定向到7002)
# 批量操作跨slot的key需要使用hash tag
# hash tag用{}包裹确保key映射到同一slot
redis-cli -c -p 7000 set {user:1000}:profile "data"
redis-cli -c -p 7000 set {user:1000}:settings "data"
# 两个key可能在不同slot,跨slot MGET会失败
redis-cli -c -p 7000 mget {user:1000}:profile {user:1000}:settings
# 使用hash tag后两个key的slot由{}内内容决定,映射到同一slot
# 1) "data"
# 2) "data"
Cluster故障转移与手动failover
当主节点故障时,Cluster会自动将从节点提升为新主节点。也可以手动触发故障转移:
# 模拟主节点7000故障
redis-cli -p 7000 shutdown nosave
# 等待Cluster自动检测并切换(cluster-node-timeout=5000ms)
sleep 10
# 检查集群状态
redis-cli -p 7001 cluster nodes
# 7000标记为fail,7003从节点被提升为master
# 手动failover(在从节点上执行)
# 连接到从节点7003
redis-cli -p 7003 cluster failover takeover
# 查看failover状态
redis-cli -p 7003 cluster nodes
# 恢复原7000节点后,将其作为新主节点的从节点
redis-cli -p 7000 cluster reset hard
# 重新加入集群
redis-cli --cluster add-node 127.0.0.1:7000 127.0.0.1:7003 --cluster-slave
Redis Sentinel哨兵模式配置
对于不需要分片的场景,Sentinel模式提供更简单的高可用方案。部署一主两从三哨兵的架构:
# redis-master.conf (主节点)
port 6379
bind 0.0.0.0
daemonize yes
appendonly yes
dir /data/redis/master
maxmemory 4gb
# redis-slave-1.conf (从节点1)
port 6380
bind 0.0.0.0
daemonize yes
appendonly yes
dir /data/redis/slave1
replicaof 127.0.0.1 6379
replica-read-only yes
# redis-slave-2.conf (从节点2)
port 6381
bind 0.0.0.0
daemonize yes
appendonly yes
dir /data/redis/slave2
replicaof 127.0.0.1 6379
replica-read-only yes
# 启动Redis实例
redis-server /etc/redis/redis-master.conf
redis-server /etc/redis/redis-slave-1.conf
redis-server /etc/redis/redis-slave-2.conf
配置三个Sentinel哨兵进程:
# sentinel-26379.conf
port 26379
bind 0.0.0.0
daemonize yes
dir /data/redis/sentinel1
# 监控主节点:名称mymaster,IP端口,2个哨兵同意才故障转移
sentinel monitor mymaster 127.0.0.1 6379 2
# 主节点无响应时间(毫秒)
sentinel down-after-milliseconds mymaster 5000
# 故障转移超时时间
sentinel failover-timeout mymaster 30000
# 故障转移时同时可写入的从节点数
sentinel parallel-syncs mymaster 1
# Sentinel认证密码(如Redis设置了requirepass)
# sentinel auth-pass mymaster yourpassword
# 通知脚本(故障转移时执行)
# sentinel notification-script mymaster /opt/redis/notify.sh
# 重新配置客户端脚本
# sentinel client-reconfig-script mymaster /opt/redis/reconfig.sh
# 复制Sentinel配置
for port in 26380 26381; do
sed "s/26379/$port/g; s/sentinel1/sentinel$((port-26378))/g" sentinel-26379.conf > sentinel-$port.conf
done
# 启动Sentinel
redis-sentinel /etc/redis/sentinel-26379.conf
redis-sentinel /etc/redis/sentinel-26380.conf
redis-sentinel /etc/redis/sentinel-26381.conf
# 查看Sentinel状态
redis-cli -p 26379 sentinel master mymaster
redis-cli -p 26379 sentinel replicas mymaster
redis-cli -p 26379 sentinel sentinels mymaster
客户端连接配置与故障转移测试
使用redis-py连接Cluster和Sentinel:
from redis.cluster import RedisCluster, ClusterNode
from redis.sentinel import Sentinel
# === Redis Cluster 客户端 ===
# 自动发现集群所有节点
nodes = [
ClusterNode('127.0.0.1', 7000),
ClusterNode('127.0.0.1', 7001),
ClusterNode('127.0.0.1', 7002),
]
rc = RedisCluster(startup_nodes=nodes, decode_responses=True)
# Cluster操作(自动路由到正确节点)
rc.set('user:1000', 'value')
rc.get('user:1000')
# 使用hash tag进行批量操作
rc.mset({'{user:1000}:name': 'Alice', '{user:1000}:age': '30'})
rc.mget('{user:1000}:name', '{user:1000}:age')
# === Sentinel 客户端 ===
sentinel = Sentinel([
('127.0.0.1', 26379),
('127.0.0.1', 26380),
('127.0.0.1', 26381),
], socket_timeout=0.5)
# 获取主节点连接
master = sentinel.master_for('mymaster', socket_timeout=0.5)
# 获取从节点连接(读操作分流到从节点)
slave = sentinel.slave_for('mymaster', socket_timeout=0.5)
master.set('key', 'value')
value = slave.get('key')
# 故障转移后,客户端会自动重新发现新的主节点
# 无需手动重连
测试Sentinel故障转移:
# 模拟主节点故障
redis-cli -p 6379 shutdown nosave
# 等待Sentinel检测(down-after-milliseconds=5000)
sleep 8
# 查看Sentinel日志,确认故障转移
redis-cli -p 26379 sentinel master mymaster | grep num-slaves
# 新主节点已选举完成
# 客户端自动重连到新主节点,无需手动干预
Redis Cluster和Sentinel两种高可用方案各有适用场景。Cluster模式通过slot分片实现水平扩展,适合数据量超过单机内存的场景,但需要客户端支持Cluster协议并注意跨slot操作限制。Sentinel模式配置简单,客户端连接透明,适合中小规模数据的读写分离和高可用需求。在实际部署中,Sentinel的down-after-milliseconds和Cluster的cluster-node-timeout参数需要根据网络环境合理设置,过短会导致误判,过长会延长故障恢复时间。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/rediscluster-ji-qun-mo-shi-bu-shu-yu-sentinel-shao-bing-gao/