Redis高可用架构选型
Redis缓存策略在数据库运维中承担着减轻后端压力、提升响应速度的关键角色。单节点Redis存在单点故障风险,生产环境必须部署高可用架构。Redis提供两种高可用方案:Sentinel(哨兵)模式适合中等规模、读写分离场景;Cluster集群模式适合大规模数据分片和高并发场景。两种方案的数据分布、故障转移机制和运维复杂度有本质区别。
Sentinel哨兵模式部署
Sentinel模式由一个或多个Sentinel实例监控Redis主从节点,当主节点故障时自动选举新的主节点。典型部署:1主2从3哨兵,共6个Redis进程。
# 目录结构
redis-sentinel/
├── redis-master.conf # 主节点配置
├── redis-slave1.conf # 从节点1配置
├── redis-slave2.conf # 从节点2配置
├── sentinel1.conf # 哨兵1配置
├── sentinel2.conf # 哨兵2配置
├── sentinel3.conf # 哨兵3配置
└── start.sh # 启动脚本
# redis-master.conf
bind 0.0.0.0
port 6379
daemonize yes
pidfile /var/run/redis-master.pid
logfile /var/log/redis/redis-master.log
dir /data/redis/master
appendonly yes
appendfsync everysec
maxmemory 4gb
maxmemory-policy allkeys-lru
requirepass YourPassword123!
masterauth YourPassword123!
# redis-slave1.conf
bind 0.0.0.0
port 6380
daemonize yes
dir /data/redis/slave1
replicaof 127.0.0.1 6379
masterauth YourPassword123!
requirepass YourPassword123!
appendonly yes
# sentinel1.conf
bind 0.0.0.0
port 26379
daemonize yes
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel auth-pass mymaster YourPassword123!
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 30000
sentinel parallel-syncs mymaster 1
关键参数说明:
sentinel monitor:监控的主节点地址和quorum值(2表示需要2个哨兵同意才能判定主节点下线)down-after-milliseconds:5秒内无响应判定为主观下线failover-timeout:故障转移超时时间30秒parallel-syncs:故障转移时同时同步的从节点数,设为1减少对性能的影响
Sentinel故障转移流程
故障转移的完整过程:
# 启动顺序
redis-server redis-master.conf
redis-server redis-slave1.conf
redis-server redis-slave2.conf
redis-sentinel sentinel1.conf
redis-sentinel sentinel2.conf
redis-sentinel sentinel3.conf
# 验证哨兵集群状态
redis-cli -p 26379
> SENTINEL master mymaster
> SENTINEL replicas mymaster
> SENTINEL sentinels mymaster
# 模拟主节点故障
redis-cli -p 6379 DEBUG SLEEP 30
# 观察故障转移过程:
# 1. 哨兵在5秒后判定主节点主观下线(SDOWN)
# 2. 2个以上哨兵同意后转为客观下线(ODOWN)
# 3. 哨兵发起leader选举
# 4. 选出优先级最高的从节点为新主节点
# 5. 其他从节点指向新主节点
# 6. 旧主节点恢复后变为从节点
Cluster集群模式部署
Cluster模式通过分片将数据分布到多个节点,支持水平扩展。最小集群:3主3从6个节点。数据按16384个slot分布,每个主节点负责一部分slot。
# 创建6个Redis节点的配置(以端口区分)
# redis-cluster/7000/redis.conf ~ redis-cluster/7005/redis.conf
port 7000 # 端口7000-7005
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
appendonly yes
appendfsync everysec
maxmemory 8gb
maxmemory-policy allkeys-lru
cluster-announce-ip 192.168.1.100 # 实际IP
cluster-announce-port 7000
cluster-announce-bus-port 17000 # 集群总线端口
# 批量启动
for port in 7000 7001 7002 7003 7004 7005; do
redis-server /opt/redis-cluster/$port/redis.conf
done
# 创建集群
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
--cluster-replicas 1表示每个主节点配一个从节点。创建后集群自动分配slot:7000-7002为主节点,各负责约5461个slot;7003-7005为从节点。
Cluster数据分片与路由
Redis Cluster使用CRC16算法计算key的slot值,公式为CRC16(key) mod 16384。客户端需要实现Cluster协议来自动路由请求:
# 查看key所在slot
redis-cli -p 7000 CLUSTER KEYSLOT mykey
# 输出:5474
# 直接操作(客户端自动路由)
redis-cli -c -p 7000 SET mykey "hello"
# 如果key不在当前节点,客户端收到MOVED重定向:
# (error) MOVED 5474 192.168.1.100:7001
# -c参数启用自动跟随重定向
# 使用hash tag确保多个key在同一个slot
SET {user:1000}:profile "data"
SET {user:1000}:settings "data"
# {user:1000}作为hash tag,两个key的slot相同
# 可以在同一条MGET命令中获取
Spring Boot集成Redis集群
在NoSQL选型应用中,Spring Data Redis提供了完善的Cluster客户端支持:
spring:
data:
redis:
cluster:
nodes:
- 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
max-redirects: 3
topology-refresh: true # 动态感知节点变化
password: YourPassword123!
lettuce:
pool:
max-active: 50
max-idle: 20
min-idle: 5
cluster:
refresh:
adaptive: true
period: 30s # 每30秒刷新集群拓扑
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setEnableTransactionSupport(true);
return template;
}
// 分布式锁
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useClusterServers()
.addNodeAddress(
"redis://192.168.1.100:7000",
"redis://192.168.1.100:7001",
"redis://192.168.1.100:7002"
)
.setPassword("YourPassword123!")
.setScanInterval(2000) // 集群状态扫描间隔
.setSlaveConnectionMinimumIdleSize(10)
.setSlaveConnectionPoolSize(64)
.setMasterConnectionMinimumIdleSize(10)
.setMasterConnectionPoolSize(64)
.setIdleConnectionTimeout(10000)
.setConnectTimeout(10000)
.setTimeout(3000)
.setRetryAttempts(3)
.setRetryInterval(1500);
return Redisson.create(config);
}
}
两种模式对比与选型
| 维度 | Sentinel哨兵 | Cluster集群 |
|---|---|---|
| 数据分片 | 不支持,全量数据在每个节点 | 支持,数据按slot分布 |
| 容量上限 | 单节点内存上限 | 所有节点内存总和 |
| 写入性能 | 单主写入瓶颈 | 多主并行写入 |
| 故障转移 | Sentinel选举新主 | 从节点自动升级 |
| 客户端复杂度 | 低,连接Sentinel获取主节点 | 高,需实现slot路由协议 |
| 运维复杂度 | 中等 | 高(slot迁移、扩缩容) |
| 跨slot操作 | 无限制 | 受限于hash tag |
数据备份恢复与持久化策略
在数据备份恢复场景中,Redis的持久化配置直接影响故障后的数据恢复能力:
# RDB快照配置
save 900 1 # 15分钟内有1个key变化则快照
save 300 10 # 5分钟内有10个key变化则快照
save 60 10000 # 1分钟内有10000个key变化则快照
# AOF配置
appendonly yes
appendfsync everysec # 每秒刷盘,平衡性能和安全
no-appendfsync-on-rewrite no
# 混合持久化(RDB+AOF)
aof-use-rdb-preamble yes # AOF重写时使用RDB格式存储全量数据
# 备份脚本
#!/bin/bash
BACKUP_DIR=/data/redis-backup/$(date +%Y%m%d)
mkdir -p $BACKUP_DIR
# 触发BGSAVE并等待完成
redis-cli -p 7000 -a YourPassword123! BGSAVE
while [ $(redis-cli -p 7000 -a YourPassword123! LASTSAVE) -le $LASTSAVE_TIME ]; do
sleep 1
done
# 复制RDB和AOF文件
cp /data/redis/7000/dump.rdb $BACKUP_DIR/7000-dump.rdb
cp /data/redis/7000/appendonly.aof $BACKUP_DIR/7000-appendonly.aof
# 发送到远程备份服务器
rsync -az $BACKUP_DIR/ backup-server:/redis-backup/
混合持久化是生产环境的推荐配置:RDB提供快速恢复能力,AOF提供更细粒度的数据保护。AOF重写时先以RDB格式写入全量数据,再追加增量AOF命令,兼顾恢复速度和数据完整性。
性能调优与常见问题
集群模式的性能调优方向:
- 大key问题:单个key超过10KB时影响网络传输,使用
redis-cli --bigkeys检测,拆分为小key - 热key问题:单个key访问量过高导致节点倾斜,使用本地缓存或
redis-cli --hotkeys检测 - 慢查询:
SLOWLOG GET查看慢查询,禁用KEYS等O(n)命令 - 内存碎片:
INFO memory查看mem_fragmentation_ratio,超过1.5时使用MEMORY PURGE
在数据库高可用架构的整体规划中,Redis集群的数据分片策略与MySQL分库分表方案的配合是常见的设计决策。MySQL按业务维度分库,Redis Cluster按slot分片,两者独立扩展,通过一致性哈希或hash tag在应用层协调数据的分布关系。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/redis-ji-qun-gao-ke-yong-bu-shu-shi-zhan-shao-bing-mo-shi/