Redis集群
一,核心概念
- 数据分片(Sharding)
- Redis 集群采用 哈希槽(Hash Slot)实现数据分片,共有 16384 个槽位。
- 每个主节点负责一部分槽位,如 3 主节点集群中,每个节点约负责 5461 个槽位(16384/3)。
- 数据定位公式:
slot = CRC16(key) % 16384
。
- 主从复制
- 每个主节点至少有一个从节点,主节点故障时,从节点自动升级为新主节点。
- 复制过程采用异步方式,保证高可用性但不保证强一致性。
- 故障转移
- 通过 Gossip 协议交换节点状态信息(Ping/Pong 消息)。
- 当半数以上主节点认为某个主节点下线时,触发故障转移。
二,Redis集群方式
1、主从复制(Master-Slave Replication)
基本概念
主从复制是 Redis 最早支持的集群方式,通过将一个 Redis 实例(主节点)的数据复制到一个或多个从节点,实现数据的冗余和读写分离。
核心特点
- 数据同步:主节点负责写入操作,从节点自动同步主节点数据,支持全量同步(RDB 快照)和增量同步(基于命令日志)。
- 读写分离:主节点处理写请求,从节点处理读请求,分担读压力。
- 高可用性基础:从节点可作为备份,但若主节点故障,需手动切换或配合哨兵模式实现自动故障转移。
优缺点
- 优点
- 实现简单,配置方便,无需额外组件。
- 读写分离提升读性能,适合读多写少场景。
- 缺点
- 主节点单点故障风险,需人工干预切换。
- 从节点数量过多可能影响主节点性能(数据同步开销)。
适用场景
- 读多写少的业务场景(如缓存、排行榜查询)。
- 对数据备份和容灾有基础需求,但无需自动故障转移的场景。
2、哨兵模式(Sentinel)
基本概念
哨兵模式是在主从复制基础上,引入哨兵节点(Sentinel)组成的监控集群,用于自动监控主从节点状态,并在主节点故障时自动选举新主节点,实现故障转移。
核心组件
- 哨兵节点:独立的 Redis 实例,负责监控主从节点健康状态,协调故障转移。
- 主从节点:与主从复制结构相同,但由哨兵管理切换。
核心流程
- 哨兵定期向主从节点发送心跳,检测节点存活状态。
- 当主节点被多数哨兵判定为 “下线”(主观下线→客观下线),触发故障转移。
- 哨兵从从节点中选举新主节点,并通知其他从节点切换到新主。
优缺点
- 优点
- 自动故障转移,无需人工干预,提升系统可用性。
- 支持多哨兵节点,避免哨兵单点故障(需部署奇数个哨兵,如 3 个)。
- 缺点
- 数据仍集中在主节点,无法突破单节点内存限制。
- 故障转移期间存在短暂服务中断(毫秒级到秒级)。
适用场景
- 对高可用性要求较高的业务(如实时数据服务)。
- 写操作频率适中,无需水平扩展的场景。
3、集群模式(Redis Cluster)
基本概念
Redis Cluster 是 Redis 3.0 后引入的分布式集群方案,通过将数据分片(Sharding)到多个节点,实现数据的水平扩展和高可用性,是目前官方推荐的分布式方案。
核心原理
- 数据分片:将键空间(0~16383)划分为 16384 个槽位(Slot),每个节点负责部分槽位,客户端通过计算键的哈希值确定对应槽位和节点。
- 节点通信:节点间通过 Gossip 协议交换状态信息,维护集群拓扑结构。
- 高可用性:每个主节点配备从节点,主节点故障时,从节点自动升级为主节点,保证槽位服务不中断。
核心特点
- 水平扩展:可通过添加节点扩展集群容量和性能,理论上无节点数量上限。
- 自动分片:无需客户端手动分片,集群自动管理槽位分配和迁移。
- 去中心化:无中心节点,每个节点都可处理读写请求,避免单点瓶颈。
优缺点
- 优点
- 支持大规模数据存储和高并发访问。
- 自动故障转移和数据均衡,运维成本较低。
- 缺点
- 实现较复杂,客户端需支持集群协议(如 Jedis、Redisson)。
- 跨节点操作(如事务、Lua 脚本)存在限制,需保证键在同一节点。
适用场景
- 数据量庞大、并发要求高的场景(如电商缓存、社交平台实时数据)。
- 需要水平扩展和高可用性的分布式系统。
4、集群方式对比与选择建议
集群方式 | 主从复制 | 哨兵模式 | Redis Cluster |
---|---|---|---|
数据分片 | 不支持 | 不支持 | 支持(16384 个槽位) |
自动故障转移 | 不支持 | 支持 | 支持 |
水平扩展 | 不支持 | 不支持 | 支持 |
高可用性 | 低(需手动切换) | 中(自动切换) | 高(多主多从) |
适合场景 | 读多写少、简单备份 | 高可用、中等规模数据 | 大规模数据、高并发 |
三,集群示例
8台主机操作是一样的安装redis 前6台搭建集群环境后2台做集群扩展
3.1先搭建集群环境
[root@localhost redis]# vim 6379.conf
# 绑定地址:允许所有 IP 访问(生产环境建议绑定具体 IP)
bind 0.0.0.0
# 开启 AOF 持久化,保证数据安全性(默认 RDB 持久化可能丢失部分数据)
appendonly yes
# 启用 Redis Cluster 集群模式
cluster-enabled yes
# 集群配置文件路径,自动生成,记录节点信息(如节点 ID、状态)
cluster-config-file nodes-6379.conf
# 节点超时时间(毫秒):超过此时间未响应则认为节点故障
cluster-node-timeout 15000
# 集群全量覆盖要求:必须所有槽位(16384 个)都有节点负责才能提供服务
# 若设置为 no,则部分槽位不可用时集群仍可读写(部分服务降级)
cluster-require-full-coverage yes
# 重启 Redis 服务(基于 6379.conf 配置)
[root@localhost bin]# /etc/init.d/redis_6379 restart
# 查看端口监听状态,确认 Redis 服务正常运行
[root@localhost bin]# netstat -anpt | grep 6379
# 输出结果说明:
# 1. 6379 端口:Redis 服务主端口,处理客户端请求
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 13591/redis-server
# 2. 16379 端口:Redis Cluster 集群总线端口(主端口 + 10000)
# 用于节点间通信(Gossip 协议),交换拓扑信息、故障检测等
tcp 0 0 0.0.0.0:16379 0.0.0.0:* LISTEN 13591/redis-server
# 3. TIME_WAIT 状态连接:客户端连接关闭后的临时状态(TCP 四次挥手)
tcp 0 0 127.0.0.1:6379 127.0.0.1:45714 TIME_WAIT -
3.2创建集群
[root@localhost bin]# redis-cli --cluster create --cluster-replicas 1 192.168.10.101:6379 192.168.10.102:6379 192.168.10.103:6379 192.168.10.104:6379 192.168.10.105:6379 192.168.10.106:6379
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.10.105:6379 to 192.168.10.101:6379
Adding replica 192.168.10.106:6379 to 192.168.10.102:6379
Adding replica 192.168.10.104:6379 to 192.168.10.103:6379
M: 189f4095a9c7687ff22b0031848c6740f8b47ca3 192.168.10.101:6379
slots:[0-5460] (5461 slots) master
M: 54c4cb5770e18a2607195ed8f10599a894def57f 192.168.10.102:6379
slots:[5461-10922] (5462 slots) master
M: 70d4f069e0bac3c765c5643331537066d8a33c26 192.168.10.103:6379
slots:[10923-16383] (5461 slots) master
S: c0b5dc5e89a506d482587a6edc52d89ded79b4aa 192.168.10.104:6379
replicates 70d4f069e0bac3c765c5643331537066d8a33c26
S: c7af1a944061b7a2206edc4c505d50186bfbd86d 192.168.10.105:6379
replicates 189f4095a9c7687ff22b0031848c6740f8b47ca3
S: bb68e02516c31a4088278acf5d0e905eee1c2fef 192.168.10.106:6379
replicates 54c4cb5770e18a2607195ed8f10599a894def57f
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 192.168.10.101:6379)
M: 189f4095a9c7687ff22b0031848c6740f8b47ca3 192.168.10.101:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: c7af1a944061b7a2206edc4c505d50186bfbd86d 192.168.10.105:6379
slots: (0 slots) slave
replicates 189f4095a9c7687ff22b0031848c6740f8b47ca3
M: 54c4cb5770e18a2607195ed8f10599a894def57f 192.168.10.102:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: bb68e02516c31a4088278acf5d0e905eee1c2fef 192.168.10.106:6379
slots: (0 slots) slave
replicates 54c4cb5770e18a2607195ed8f10599a894def57f
M: 70d4f069e0bac3c765c5643331537066d8a33c26 192.168.10.103:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: c0b5dc5e89a506d482587a6edc52d89ded79b4aa 192.168.10.104:6379
slots: (0 slots) slave
replicates 70d4f069e0bac3c765c5643331537066d8a33c26
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
以下是 Redis Cluster 创建命令及输出的详细注释:
创建集群命令
redis-cli --cluster create \
--cluster-replicas 1 \ # 每个主节点分配1个从节点(主从比例1:1)
192.168.10.101:6379 \ # 节点1(主节点)
192.168.10.102:6379 \ # 节点2(主节点)
192.168.10.103:6379 \ # 节点3(主节点)
192.168.10.104:6379 \ # 节点4(从节点)
192.168.10.105:6379 \ # 节点5(从节点)
192.168.10.106:6379 # 节点6(从节点)
- 原理:将 6 个节点自动分配为 3 主 3 从,每个主节点对应一个从节点,实现高可用。
槽位分配结果
Master[0] -> Slots 0 - 5460 # 主节点1负责槽位0~5460(共5461个)
Master[1] -> Slots 5461 - 10922 # 主节点2负责槽位5461~10922(共5462个)
Master[2] -> Slots 10923 - 16383 # 主节点3负责槽位10923~16383(共5461个)
- 槽位机制:Redis Cluster 将所有数据划分为 16384 个槽位,每个主节点负责一部分槽位。
- 分配逻辑:自动均匀分配槽位(尽量平均,但因总数无法整除,主节点 2 多 1 个槽位)。
主从关系分配
Adding replica 192.168.10.105:6379 to 192.168.10.101:6379 # 节点5是节点1的从节点
Adding replica 192.168.10.106:6379 to 192.168.10.102:6379 # 节点6是节点2的从节点
Adding replica 192.168.10.104:6379 to 192.168.10.103:6379 # 节点4是节点3的从节点
- 高可用保障:当主节点故障时,对应的从节点会自动升级为主节点继续服务。
集群拓扑结构(简化版)
主节点1 (101:6379)
└── 从节点5 (105:6379)
主节点2 (102:6379)
└── 从节点6 (106:6379)
主节点3 (103:6379)
└── 从节点4 (104:6379)
集群验证输出
[OK] All nodes agree about slots configuration. # 所有节点槽位配置一致
[OK] All 16384 slots covered. # 所有槽位都有主节点负责(无缺失)
- 关键点
- 槽位覆盖完整:所有 16384 个槽位均被分配,集群可正常提供服务。
- 节点状态一致:通过 Gossip 协议,所有节点达成槽位分配共识。
3.3测试集群
6个随便登录一个都可以
# 连接到集群节点 192.168.10.106:6379,-c 参数启用集群模式(支持自动重定向)
[root@localhost bin]# redis-cli -h 192.168.10.106 -p 6379 -c
# 设置键值对:name=zhangsan
192.168.10.106:6379> set name zhangsan
# 自动重定向到槽位 5798 所在的节点 192.168.10.102:6379
-> Redirected to slot [5798] located at 192.168.10.102:6379
OK
# 从重定向后的节点获取键值
192.168.10.102:6379> get name
"zhangsan"
# 查看集群拓扑结构
192.168.10.102:6379> cluster nodes
# 节点格式:<节点ID> <IP:端口>@<总线端口> <角色> <主节点ID> <最后一次心跳时间> <节点ID> <状态> <槽位范围>
# 从节点 1(106:6379):复制主节点 102:6379
bb68e02516c31a4088278acf5d0e905eee1c2fef 192.168.10.106:6379@16379 slave 54c4cb5770e18a2607195ed8f10599a894def57f 0 1744018709015 6 connected
# 从节点 2(105:6379):复制主节点 101:6379
c7af1a944061b7a2206edc4c505d50186bfbd86d 192.168.10.105:6379@16379 slave 189f4095a9c7687ff22b0031848c6740f8b47ca3 0 1744018709859 5 connected
# 从节点 3(104:6379):复制主节点 103:6379
c0b5dc5e89a506d482587a6edc52d89ded79b4aa 192.168.10.104:6379@16379 slave 70d4f069e0bac3c765c5643331537066d8a33c26 0 1744018710901 4 connected
# 主节点 3(103:6379):负责槽位 10923-16383
70d4f069e0bac3c765c5643331537066d8a33c26 192.168.10.103:6379@16379 master - 0 1744018705678 3 connected 10923-16383
# 主节点 1(101:6379):负责槽位 0-5460
189f4095a9c7687ff22b0031848c6740f8b47ca3 192.168.10.101:6379@16379 master - 0 1744018708807 1 connected 0-5460
# 主节点 2(102:6379,当前连接节点):负责槽位 5461-10922
54c4cb5770e18a2607195ed8f10599a894def57f 192.168.10.102:6379@16379 myself,master - 0 0 2 connected 5461-10922
3.4扩展集群
概念
- 新加入的节点在初始阶段没有任何数据分片,因为 Redis 集群的数据是通过哈希槽(Hash Slot)分配到各个主节点的。在现有的集群环境下添加新的节点是没有哈希槽的因为哈希槽已经被分完了
- 新加入的节点状态信息都是master
第一个方式
[root@localhost bin]# redis-cli -c -p 6379 cluster meet 192.168.10.107 6379
OK
[root@localhost bin]# redis-cli
127.0.0.1:6379> cluster nodes
be80d7bb5b0316220defa9a1dc2c2156b4ff486d 192.168.10.107:6379@16379 master - 0 1744019619971 0 connected
第二个方式
[root@localhost bin]# redis-cli --cluster add-node 192.168.10.108:6379 192.168.10.101:6379
>>> Adding node 192.168.10.108:6379 to cluster 192.168.10.101:6379
>>> Performing Cluster Check (using node 192.168.10.101:6379)
M: 189f4095a9c7687ff22b0031848c6740f8b47ca3 192.168.10.101:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: be80d7bb5b0316220defa9a1dc2c2156b4ff486d 192.168.10.107:6379
slots: (0 slots) master
S: c7af1a944061b7a2206edc4c505d50186bfbd86d 192.168.10.105:6379
slots: (0 slots) slave
replicates 189f4095a9c7687ff22b0031848c6740f8b47ca3
M: 54c4cb5770e18a2607195ed8f10599a894def57f 192.168.10.102:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: bb68e02516c31a4088278acf5d0e905eee1c2fef 192.168.10.106:6379
slots: (0 slots) slave
replicates 54c4cb5770e18a2607195ed8f10599a894def57f
M: 70d4f069e0bac3c765c5643331537066d8a33c26 192.168.10.103:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: c0b5dc5e89a506d482587a6edc52d89ded79b4aa 192.168.10.104:6379
slots: (0 slots) slave
replicates 70d4f069e0bac3c765c5643331537066d8a33c26
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 192.168.10.108:6379 to make it join the cluster.
[OK] New node added correctly.
区别
命令 | 操作对象 | 操作方式 | 适用场景 |
---|---|---|---|
redis-cli -c -p 6379 cluster meet 192.168.10.107 6379 | 单个节点(客户端视角) | 通过执行 CLUSTER MEET 命令直接操作 | 手动添加节点,需逐个执行命令 |
redis-cli --cluster add-node 192.168.10.108:6379 192.168.10.101:6379 | 整个集群(工具视角) | 使用 redis-cli --cluster 工具批量操作 | 自动化添加节点,工具自动处理集群逻辑 |
详细区别
1. cluster meet
命令
-
操作对象:单个 Redis 节点
-
执行方式:通过客户端连接到现有节点(如
-p 6379
),执行CLUSTER MEET
命令 -
核心逻辑:
- 通知当前连接的节点(如
192.168.10.101:6379
)去 “认识” 新节点(192.168.10.107:6379
) - 现有节点与新节点建立 Gossip 通信,交换拓扑信息
- 需在每个现有节点上都执行一次该命令,才能让整个集群发现新节点
- 通知当前连接的节点(如
-
示例流程:
# 1. 连接到节点101,让它认识新节点107 redis-cli -c -h 192.168.10.101 -p 6379 cluster meet 192.168.10.107 6379 # 2. 重复上述操作,连接到节点102和103,让它们也认识新节点107 redis-cli -c -h 192.168.10.102 -p 6379 cluster meet 192.168.10.107 6379 redis-cli -c -h 192.168.10.103 -p 6379 cluster meet 192.168.10.107 6379
2. redis-cli --cluster add-node
命令
-
操作对象:整个 Redis 集群
-
执行方式:通过
redis-cli
的集群管理工具(--cluster
参数)操作 -
核心逻辑:
- 工具自动连接到种子节点(如
192.168.10.101:6379
) - 获取集群拓扑信息
- 自动向所有现有节点发送
CLUSTER MEET
命令,将新节点(192.168.10.108:6379
)加入集群 - 自动更新集群配置
- 工具自动连接到种子节点(如
-
示例流程:
# 仅需一次命令,工具会自动处理所有节点 redis-cli --cluster add-node 192.168.10.108:6379 192.168.10.101:6379
关键差异点总结
维度 | cluster meet | redis-cli --cluster add-node |
---|---|---|
操作复杂度 | 高(需在每个节点执行一次) | 低(单命令自动处理) |
拓扑感知 | 需手动同步所有节点 | 自动同步整个集群 |
错误处理 | 需手动处理网络分区等异常 | 工具自动处理常见异常 |
角色指定 | 默认添加为主节点 | 可通过 --cluster-slave 指定从节点 |
适用场景 | 调试、手动维护 | 生产环境自动化部署 |
3.4修改master为slave
刚才我们把107和108加入到集群环境内107和108初始状态都是master这里我将108设置为107的slave
# 连接到 Redis 节点 192.168.10.108:6379(未使用 -c 参数,以单机模式连接)
[root@localhost redis]# redis-cli -h 192.168.10.108 -p 6379
# 在集群模式下,将当前节点(108:6379)设置为指定主节点的从节点
# CLUSTER REPLICATE <主节点ID> 命令用于让当前节点复制另一个主节点的数据
192.168.10.108:6379> cluster replicate be80d7bb5b0316220defa9a1dc2c2156b4ff486d
OK
3.5删除节点
1清空槽位信息
# 连接到 Redis 节点 192.168.10.102:6379(未使用 -c 参数,以单机模式连接)
[root@localhost bin]# redis-cli -h 192.168.10.102 -p 6379
# 清空当前数据库中的所有键值对(危险操作!)
# FLUSHALL 命令会删除当前节点上的所有数据,无论该节点是主节点还是从节点
192.168.10.102:6379> flushall
OK
2删除节点
# 使用 redis-cli 的集群管理工具删除指定节点
# 命令格式:redis-cli --cluster del-node <集群任意节点> <待删除节点ID>
[root@localhost bin]# redis-cli --cluster del-node 192.168.10.102:6379 54c4cb5770e18a2607195ed8f10599a894def57f
3.6重新分配哈希槽
# 使用 redis-cli 的集群管理工具对集群进行自动负载均衡
# 命令格式:redis-cli --cluster rebalance [选项] <集群种子节点>
[root@localhost bin]# redis-cli --cluster rebalance \
--cluster-threshold 1 \ # 设置平衡阈值为 1,表示节点间槽位数量差异超过 1 时触发平衡
--cluster-use-empty-masters \ # 允许将槽位迁移到空的主节点(即尚未分配槽位的主节点)
192.168.10.101:6379 # 指定集群中的任意节点作为入口点,用于获取集群拓扑信息
关键点解析
-
负载均衡原理
- Redis 集群将 16384 个槽位分配给各个主节点
- 随着节点的添加或移除,槽位分布可能变得不均匀
rebalance
命令会自动将槽位从负载高的节点迁移到负载低的节点
-
参数详解
-
--cluster-threshold 1
- 控制平衡的敏感度
- 值越小,触发平衡的频率越高
- 例如:当阈值为 1 时,若某个主节点比其他主节点多 2 个槽位,就会触发迁移
-
--cluster-use-empty-masters
- 特别适用于新添加的空主节点
- 允许将槽位迁移到这些空节点,充分利用新资源
- 若不指定该参数,空主节点将不会参与负载均衡
-
-
执行流程
# 1. 工具连接到指定节点(192.168.10.101:6379) # 2. 获取集群拓扑信息(节点列表、槽位分配) # 3. 计算每个节点的负载情况 # 4. 确定需要迁移的槽位及其目标节点 # 5. 执行槽位迁移(每次迁移一个槽位,包含该槽位下的所有键)