Redis Cluster是Redis官方提供的分布式方案,通过槽位(Slot)分区实现数据分片,支持自动故障转移和在线扩缩。与哨兵模式不同,Cluster模式无中心节点,每个节点都存储完数据的子集,客户端可连接任意节点,节点间通过Gossip协议同步集群状态。
Redis Cluster槽位分配原理
Redis Cluster将数据划分为16384个槽位,每个节点负责一部分槽位。键到槽位的映射使用CRC16算法,公式为 slot = CRC16(key) mod 16384。节点数变化时,槽位在节点间迁移,但总槽位数始终为16384。
# 创建6节点集群(3主3从)
# 节炱1: 7000(主) 7001(从)
# 节炲2: 7002(主) 7003(从)
# 节炲3: 7004(主) 7005(从)
# 节炱1配置文件 redis-7000.conf
port 7000
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
appendonly yes
appendfsync everysec
# 启动所有节点
redis-server redis-7000.conf
redis-server redis-7001.conf
redis-server redis-7002.conf
redis-server redis-7003.conf
redis-server redis-7004.conf
redis-server redis-7005.conf
# 创建集群
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 nodes
# 输出:
# id 7000 master - 0-5460 slots
# id 7002 master - 5461-10922 slots
# id 7004 master - 10923-16383 slots
# id 7001 slave of 7000
# id 7003 slave of 7002
# id 7005 slave of 7004
客户端连接与MOVED重定向
# 客户端直接连接某个节点
redis-cli -p 7000
> SET user:1001 "hello"
# 如果key不在该节点的槽位范围,返回MOVED错误
# (error) MOVED 5798 127.0.0.1:7002
# 表示slot 5798在节炲7002上
# 使用-c参数启用集群模式(自动MOVED重定向)
redis-cli -c -p 7000
> SET user:1001 "hello"
# -> Redirected to slot [5798] located at 127.0.0.1:7002
# OK
# Java客户端连接示例
import redis.clients.jedis.*;
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("127.0.0.1", 7000));
nodes.add(new HostAndPort("127.0.0.1", 7002));
nodes.add(new HostAndPort("127.0.0.1", 7004));
JedisCluster cluster = new JedisCluster(
nodes,
5000, // 连接超时
10, // 重试次数
new GenericObjectPoolConfig<>()
);
cluster.set("user:1001", "hello");
String val = cluster.get("user:1001");
// JedisCluster自动处理MOVED重定向和连接池
故障转移机制详解
当某个主节点故障,Cluster需要将其上的槽位转移到对应的从节点。转移过程分为此步:检测故障、确认下线、提升从节点、广播状态。
# 模拟主节炲7000故障
redis-cli -p 7000 DEBUG sleep 10
# 等待cluster-node-timeout(5秒)96后,其他节点标记它为PFAIL
# 再经过一个timeout周期后,标记为FAIL
# 从节炲7001发起选举,提升为主节点
# 查看转移后的状态
redis-cli -p 7002 cluster nodes
# 原从节炲7001已成为主节炲
# 原主节炲7000标记为fail
# 故障恢复后重新加入集群
redis-server redis-7000.conf
redis-cli --cluster add-node 127.0.0.1:7000 127.0.0.1:7002 --cluster-slave --cluster-master-id <node7001_id>
# 7000作为7001(现主)的从节点重新加入
扩缩节点与槽位迁移
# 添加新节炲(7006主 7007从)
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7000 --cluster-slave --cluster-master-id <node7006_id>
# 分配槽位到新节炲
redis-cli --cluster reshard 127.0.0.1:7000
# How many slots? 4096
# Receiving node ID? <node7006_id>
# Source node ID? all
# 从所有现有主节炲均分槽位给新节炲
# 查看槽位分配
redis-cli -p 7000 cluster slots
# 1) 1) (integer) 0
# 2) (integer) 4095
# 3) 1) "127.0.0.1" 2) (integer) 7006 # 新节炲分担的槽位
# 2) 1) (integer) 4096
# 2) (integer) 8191
# 3) 1) "127.0.0.1" 2) (integer) 7000
# ...
# 使用redis-cli自动均衡槽位
redis-cli --cluster rebalance 127.0.0.1:7000 --cluster-threshold 1 --cluster-simulate
Spring Boot集成Redis Cluster
# application.yml
spring:
redis:
cluster:
nodes:
- 192.168.1.10:7000
- 192.168.1.10:7001
- 192.168.1.11:7002
- 192.168.1.11:7003
- 192.168.1.12:7004
- 192.168.1.12:7005
max-redirects: 3
lettuce:
pool:
max-active: 16
max-idle: 8
min-idle: 2
cluster:
refresh:
adaptive: true
period: 30s
// Java配置
@Configuration
public class RedisClusterConfig {
@Bean
public LettuceConnectionFactory redisConnectionFactory(
RedisClusterConfiguration clusterConfig) {
clusterConfig.setMaxRedirects(3);
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.readFrom(ReadFrom.REPLICA_PREFERRED) // 读操作优先读从节炲
.commandTimeout(Duration.ofSeconds(3))
.build();
return new LettuceConnectionFactory(clusterConfig, clientConfig);
}
@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());
return template;
}
}
Redis Cluster的设计理念是去中心化,每个节点都能独立服务。槽位机制使得数据分片对客户端透明,客户端可连接任意节点并通过MOVED重定向找到目标节点。生产环境建议至少6个节炲(3主3从),不同机房部署避免单机架集故障。应用层需处理好跨槽位的多键操作,使用hash tag(如{user:1001}:name、{user:1001}:age)确保相关键落在同一槽位。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/rediscluster-ji-qun-bu-shu-shi-zhan-cao-wei-fen-pei-yu-gu/