Redis集群 #
一、集群概述 #
1.1 什么是Redis集群 #
Redis集群是Redis的分布式实现:
- 数据分片:数据分布在多个节点
- 高可用:每个分片有主从复制
- 自动故障转移:主节点故障自动切换
text
Redis集群架构:
┌─────────────────────────────────────────────────────────┐
│ Redis Cluster │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Master 1 │ │ Master 2 │ │ Master 3 │ │
│ │ 槽 0-5460 │ │ 槽 5461-10922│ │槽 10923-16383│ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐ │
│ │ Slave 1 │ │ Slave 2 │ │ Slave 3 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
│ 客户端 ────────────────────────────────────────────▶ │
│ 根据键的槽位路由到对应节点 │
└─────────────────────────────────────────────────────────┘
1.2 集群特点 #
text
Redis集群特点:
┌─────────────────────────────────────────────┐
│ 1. 数据分片 │
│ - 16384个槽位 │
│ - 分布在多个节点 │
│ - 自动分配 │
│ │
│ 2. 高可用 │
│ - 每个分片有主从 │
│ - 自动故障转移 │
│ - 最少3主3从 │
│ │
│ 3. 去中心化 │
│ - 无中心节点 │
│ - Gossip协议通信 │
│ - 每个节点平等 │
│ │
│ 4. 客户端路由 │
│ - 客户端缓存槽位映射 │
│ - MOVED重定向 │
│ - ASK重定向 │
└─────────────────────────────────────────────┘
二、槽位机制 #
2.1 槽位分配 #
text
Redis集群槽位:
- 总槽位:16384个
- 每个键属于一个槽位
- 槽位分布在多个节点
槽位计算:
CRC16(key) % 16384
示例:
key1 → CRC16(key1) % 16384 = 1234
key2 → CRC16(key2) % 16384 = 5678
2.2 槽位分布 #
text
3主节点槽位分布:
┌─────────────────────────────────────────────┐
│ Master 1: 槽 0 - 5460 │
│ Master 2: 槽 5461 - 10922 │
│ Master 3: 槽 10923 - 16383 │
└─────────────────────────────────────────────┘
每个主节点负责约1/3的槽位
2.3 哈希标签 #
bash
# 哈希标签:确保相关键在同一个槽位
# 使用{}指定哈希标签部分
SET user:{1001}:name "John"
SET user:{1001}:age 25
SET user:{1001}:email "john@example.com"
# 这三个键都在同一个槽位
# 因为只计算{1001}的槽位
# 查看键的槽位
CLUSTER KEYSLOT user:{1001}:name
# (integer) 1234
三、搭建集群 #
3.1 准备节点 #
bash
# 创建6个节点配置文件
# redis-7000.conf
port 7000
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
# redis-7001.conf ~ redis-7005.conf 类似
# 只需修改端口号
# 启动6个节点
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
3.2 创建集群 #
bash
# 使用redis-cli创建集群
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
# 输出:
# >>> Performing hash slots allocation on 6 nodes...
# Master[0] -> Slots 0 - 5460
# Master[1] -> Slots 5461 - 10922
# Master[2] -> Slots 10923 - 16383
# Adding replica 127.0.0.1:7004 to 127.0.0.1:7000
# Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
# Adding replica 127.0.0.1:7003 to 127.0.0.1:7002
# 输入yes确认
3.3 Docker Compose方式 #
yaml
# docker-compose.yml
version: '3'
services:
redis-7000:
image: redis:7.0
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes --port 7000
ports:
- "7000:7000"
- "17000:17000"
redis-7001:
image: redis:7.0
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes --port 7001
ports:
- "7001:7001"
- "17001:17001"
redis-7002:
image: redis:7.0
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes --port 7002
ports:
- "7002:7002"
- "17002:17002"
redis-7003:
image: redis:7.0
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes --port 7003
ports:
- "7003:7003"
- "17003:17003"
redis-7004:
image: redis:7.0
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes --port 7004
ports:
- "7004:7004"
- "17004:17004"
redis-7005:
image: redis:7.0
command: redis-server --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes --port 7005
ports:
- "7005:7005"
- "17005:17005"
四、集群操作 #
4.1 连接集群 #
bash
# 使用-c选项连接集群
redis-cli -c -p 7000
# 自动重定向
127.0.0.1:7000> SET key1 value1
-> Redirected to slot [9189] located at 127.0.0.1:7001
OK
127.0.0.1:7001> GET key1
"value1"
4.2 查看集群信息 #
bash
# 查看集群信息
CLUSTER INFO
# 输出:
# cluster_state:ok
# cluster_slots_assigned:16384
# cluster_slots_ok:16384
# cluster_slots_pfail:0
# cluster_slots_fail:0
# cluster_known_nodes:6
# cluster_size:3
# 查看集群节点
CLUSTER NODES
# 输出:
# 节点ID 地址 角色 槽位等信息
4.3 查看槽位 #
bash
# 查看槽位分布
CLUSTER SLOTS
# 输出:
# 1) 1) (integer) 0
# 2) (integer) 5460
# 3) 1) "127.0.0.1"
# 2) (integer) 7000
# 3) "node-id"
# 4) 1) "127.0.0.1"
# 2) (integer) 7003
# 3) "replica-node-id"
4.4 添加节点 #
bash
# 添加主节点
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 <node-id>
# 重新分配槽位
redis-cli --cluster reshard 127.0.0.1:7000
4.5 删除节点 #
bash
# 先迁移槽位
redis-cli --cluster reshard 127.0.0.1:7000
# 删除节点
redis-cli --cluster del-node 127.0.0.1:7000 <node-id>
五、故障转移 #
5.1 自动故障转移 #
text
故障转移过程:
┌─────────────────────────────────────────────────────────┐
│ 1. 主节点故障 │
│ - 其他节点检测到主节点下线 │
│ - 标记为FAIL │
├─────────────────────────────────────────────────────────┤
│ 2. 从节点选举 │
│ - 从节点发起选举 │
│ - 其他主节点投票 │
│ - 获得多数票的从节点成为新主节点 │
├─────────────────────────────────────────────────────────┤
│ 3. 槽位转移 │
│ - 新主节点接管槽位 │
│ - 更新集群配置 │
├─────────────────────────────────────────────────────────┤
│ 4. 客户端更新 │
│ - 客户端更新槽位映射 │
│ - 继续提供服务 │
└─────────────────────────────────────────────────────────┘
5.2 手动故障转移 #
bash
# 连接从节点
redis-cli -p 7003
# 手动故障转移
CLUSTER FAILOVER
# 强制故障转移(不等待主节点确认)
CLUSTER FAILOVER FORCE
# 接管故障主节点
CLUSTER FAILOVER TAKEOVER
六、客户端使用 #
6.1 连接集群 #
python
# Python示例
from redis.cluster import RedisCluster
# 连接集群
rc = RedisCluster(
host='127.0.0.1',
port=7000,
decode_responses=True
)
# 使用
rc.set('key', 'value')
value = rc.get('key')
6.2 Java示例 #
java
// Java示例 (Jedis)
Set<HostAndPort> nodes = new HashSet<>();
nodes.add(new HostAndPort("127.0.0.1", 7000));
nodes.add(new HostAndPort("127.0.0.1", 7001));
nodes.add(new HostAndPort("127.0.0.1", 7002));
JedisCluster jedisCluster = new JedisCluster(nodes);
jedisCluster.set("key", "value");
String value = jedisCluster.get("key");
七、集群限制 #
7.1 限制说明 #
text
Redis集群限制:
1. 批量操作限制
┌─────────────────────────────────────────────┐
│ MGET/MSET等批量操作 │
│ 只能操作同一个槽位的键 │
│ 使用哈希标签解决 │
└─────────────────────────────────────────────┘
2. 事务限制
┌─────────────────────────────────────────────┐
│ 事务中的键必须在同一个槽位 │
│ 使用哈希标签解决 │
└─────────────────────────────────────────────┘
3. Lua脚本限制
┌─────────────────────────────────────────────┐
│ Lua脚本中的键必须在同一个槽位 │
│ 使用哈希标签解决 │
└─────────────────────────────────────────────┘
4. 数据库限制
┌─────────────────────────────────────────────┐
│ 集群只能使用数据库0 │
│ 不能使用SELECT命令 │
└─────────────────────────────────────────────┘
7.2 解决方案 #
bash
# 使用哈希标签
# 批量操作
MSET user:{1001}:name "John" user:{1001}:age 25
# 事务
MULTI
SET user:{1001}:name "John"
SET user:{1001}:age 25
EXEC
# Lua脚本
EVAL "redis.call('SET', KEYS[1], ARGV[1]); redis.call('SET', KEYS[2], ARGV[2])" 2 user:{1001}:name user:{1001}:age "John" 25
八、最佳实践 #
8.1 集群规模 #
text
集群规模建议:
- 最小:3主3从
- 推荐:5主5从或更多
- 单节点数据量:不超过10GB
- 总数据量:不超过100GB
8.2 网络配置 #
bash
# 配置集群总线端口
# 集群总线端口 = 普通端口 + 10000
# 例如:7000端口的集群总线端口是17000
# 防火墙需要开放两个端口
# 普通端口:7000
# 集群总线端口:17000
8.3 监控指标 #
bash
# 监控集群状态
CLUSTER INFO
# 关注指标
# cluster_state: ok
# cluster_slots_assigned: 16384
# cluster_slots_ok: 16384
# cluster_known_nodes: 6
九、总结 #
集群命令:
| 命令 | 说明 |
|---|---|
| CLUSTER INFO | 查看集群信息 |
| CLUSTER NODES | 查看节点信息 |
| CLUSTER SLOTS | 查看槽位分布 |
| CLUSTER KEYSLOT | 查看键的槽位 |
| CLUSTER FAILOVER | 故障转移 |
集群特点:
| 特点 | 说明 |
|---|---|
| 数据分片 | 16384个槽位 |
| 高可用 | 主从复制+故障转移 |
| 去中心化 | Gossip协议 |
| 自动路由 | MOVED/ASK重定向 |
下一步,让我们学习Redis运维管理!
最后更新:2026-03-27