目录
Redis集群方式
主从模式
基本概念:主从模式是一种数据备份和读写分离的模式。在这种模式下,有一个主节点(Master)和一个或多个从节点(Slave)。主节点负责处理所有的写操作,而从节点则复制主节点的数据,实现数据的冗余和备份。读操作可以在主节点和从节点上进行,从而实现读写分离,提高系统性能。
工作原理:主节点将写操作记录在内存中的缓冲区,从节点从主节点获取这些写操作记录,并在自己的数据库上执行这些操作,从而保持与主节点的数据一致。
优点:
- 实现数据冗余,提高数据可靠性。
- 读写分离,提高系统性能。
缺点:
- 主节点故障时,需要手动切换到从节点,故障恢复时间较长。
- 主节点承担所有写操作,可能成为性能瓶颈。
- 无法实现数据分片,受单节点内存限制。
哨兵模式
基本概念:哨兵模式是在主从模式的基础上增加了故障转移的功能。哨兵模式下,除了主节点和从节点,还有一个或多个哨兵节点(Sentinel)。哨兵节点的主要任务是监控主节点和从节点的运行状态,并在主节点发生故障时,自动将从节点提升为主节点。
工作原理:哨兵节点会定期检查主节点和从节点的运行状态。如果发现主节点发生故障,哨兵节点会在从节点中选举出一个新的主节点,并通知其他的从节点和哨兵节点。此外,哨兵节点还可以接收客户端的查询请求,返回当前的主节点信息,从而实现客户端的透明切换。
优点:
- 自动故障转移,提高系统的高可用性。
- 具有主从复制模式的所有优点,如数据冗余和读写分离。
缺点:
- 配置和管理相对复杂。
- 依然无法实现数据分片,受单节点内存限制。
集群模式
基本概念:集群模式是一种分布式的解决方案,它允许多个Redis节点(服务器)协同工作,提供更高的性能和可用性。在这种模式下,数据被分片存储在多个节点上,每个节点负责一部分数据的读写。
工作原理:Redis集群使用一种叫做哈希槽的技术来实现数据的分片。集群将数据分为16384个槽位,每个节点负责管理一部分槽位。当一个键需要被存储时,Redis会根据键的值计算出一个哈希值,然后根据哈希值决定将这个键存储在哪个节点上。这样,读写请求就可以在多个节点上并行处理,提高了系统的性能。
优点:
- 实现数据的水平扩展,提高了系统的性能和存储容量。
- 实现高可用性,即使某个节点发生故障,系统仍然可以继续提供服务。
缺点:
- 配置和维护相对复杂,需要管理多个节点。
- 某些操作,如多键操作和事务,可能会受到限制。
Redis 集群模式简介
Redis 集群模式(Redis Cluster)是一种分布式、去中心化的高可用解决方案,旨在解决单机和主从模式下的内存限制和单点故障问题。通过数据分片和自动故障转移,集群模式可实现水平扩展和高可用性,适用于大规模数据存储和高并发场景。
核心特性
- 数据分片(Sharding)
- 数据被分配到 16384 个哈希槽(Hash Slot) 中,每个节点负责一部分槽位。
- 键的哈希值决定其存储位置(例如:
CRC16(key) % 16384
)。 - 示例:若节点 A 负责槽位 0-5460,则键
"user:1000"
可能存储在节点 A。
- 自动故障转移(Failover)
- 节点间通过 Gossip 协议 通信,监控彼此状态。
- 若主节点故障,其从节点会自动选举为新主节点(基于 Raft 算法 的变种)。
- 客户端通过重定向(
MOVED
或ASK
指令)自动切换到新主节点。
- 高可用性
- 每个主节点可配置一个或多个从节点,实现 N+1 冗余。
- 集群要求至少 3 个主节点(推荐 3 主 3 从),以避免脑裂(Split-Brain)问题。
- 水平扩展
- 新增节点时,通过 重新分片(Resharding) 动态调整槽位分配。
- 无需停机,支持在线扩容。
优势与局限
优势 | 局限 |
---|---|
- 线性扩展存储和计算能力 | - 跨节点事务和多键操作受限 |
- 自动故障转移,无需哨兵 | - 键分布不均可能导致负载倾斜 |
- 数据分片减少单节点内存压力 | - 配置复杂,需处理网络分区风险 |
- 客户端透明重定向(支持智能客户端) | - 不支持 LRANGE 等大范围查询优化 |
适用场景
- 大规模数据存储:单节点内存不足时(如 TB 级数据)。
- 高并发读写:通过分片分散请求压力。
- 需要自动故障转移:避免人工干预,提升运维效率。
不适用场景:
- 需要强一致性(集群最终一致性)。
- 依赖多键操作(如
MGET
跨节点键)。 - 复杂事务(跨节点事务需客户端处理)。
与其他模式的对比
模式 | 扩展性 | 高可用性 | 数据一致性 | 适用场景 |
---|---|---|---|---|
主从模式 | 否 | 手动切换 | 强一致性 | 小规模数据、读多写少 |
哨兵模式 | 否 | 自动切换 | 强一致性 | 高可用性要求高的场景 |
集群模式 | 是 | 自动切换 | 最终一致性 | 大规模数据、高并发、分布式 |
部署建议
- 节点数量:奇数个主节点(如 3、5、7),避免脑裂。
- 网络要求:低延迟、高带宽,避免跨机房部署(除非使用 Proxy)。
- 客户端支持:使用支持集群的客户端(如 Jedis Cluster、Lettuce)。
Redis 多从节点(Slave)选举机制详解
在 Redis 的主从复制和哨兵模式中,当主节点(Master)发生故障时,需要从多个从节点中选举出一个新的主节点。这一过程由 哨兵(Sentinel) 监控并主导,以下是其核心机制和关键点:
选举触发条件
- 主节点故障:哨兵通过定期心跳检测(每秒一次)发现主节点不可达(如无响应或超时)。
- 主观下线(Subjectively Down):单个哨兵认为主节点故障。
- 客观下线(Objectively Down):多数哨兵(
quorum
配置)达成共识,确认主节点故障。
选举过程(基于 Raft 算法的变种)
- 筛选候选从节点
- 优先级(Slave Priority):优先选择配置了较高优先级的从节点(通过
replica-priority
参数设置,默认 100)。 - 数据完整性:选择复制偏移量(
offset
)最大的从节点(即数据最接近主节点)。 - 运行 ID 排序:若偏移量相同,选择运行 ID 较小的从节点(Redis 启动时生成,唯一且固定)。
- 优先级(Slave Priority):优先选择配置了较高优先级的从节点(通过
- 执行故障转移
- 哨兵向选定的从节点发送
SLAVEOF NO ONE
命令,将其提升为主节点。 - 新主节点开始处理写请求,其他从节点自动复制新主节点的数据。
- 哨兵更新集群配置,通知客户端主节点变更(通过发布/订阅或客户端重定向)。
- 哨兵向选定的从节点发送
关键规则与注意事项
- 多数哨兵共识:选举需满足
quorum
(如 3 个哨兵中至少 2 个同意),避免脑裂(Split-Brain)。 - 避免循环选举:哨兵通过
leader epoch
标记选举轮次,防止重复投票。 - 客户端影响:
- 客户端需支持哨兵模式(如 Jedis SentinelPool),自动重连新主节点。
- 短暂不可用(故障转移期间通常 <10 秒),但依赖客户端重试机制。
示例场景
假设集群配置如下:
- 主节点:
M
- 从节点:
S1
(优先级 100,偏移量 1000)、S2
(优先级 50,偏移量 950)、S3
(优先级 100,偏移量 1000)
选举结果:
- 哨兵优先选择优先级高的从节点,排除
S2
。 S1
和S3
偏移量相同,选择运行 ID 较小的节点(假设为S1
)。S1
被提升为主节点,S3
和其他从节点开始复制S1
。
常见问题与优化
问题 1:多个哨兵同时发起选举,如何避免冲突?
解答:哨兵通过leader epoch
标记选举轮次,只有最新轮次的选举结果有效。问题 2:如何减少选举时间?
解答:- 降低
down-after-milliseconds
(默认 30 秒)和failover-timeout
(默认 180 秒)以加速检测。 - 增加哨兵节点数量(奇数个,如 3、5),提高共识速度。
- 降低
问题 3:如何避免数据丢失?
解答:- 配置
min-slaves-to-write
和min-slaves-max-lag
,确保至少一个从节点同步数据。 - 使用半同步复制(需 Redis 6.0+ 或第三方模块)。
- 配置
与其他模式的对比
模式 | 选举机制 | 适用场景 |
---|---|---|
哨兵模式 | 哨兵主导,基于优先级和偏移量 | 高可用性要求高的生产环境 |
Redis 集群 | 无传统选举,主节点故障时从节点直接升级 | 大规模数据分片,自动故障转移 |
实例一:三主三从,二扩展,成四主四从
八台redis同时配置
[root@localhost ~]# dnf -y install gcc
关闭防火墙及系统内核
[root@localhost ~]# systemctl stop firewalld
[root@localhost ~]# setenforce 0
压缩redis并编译
[root@localhost redis-5.0.14]# tar zxf redis
[root@localhost redis-5.0.14]# cd
[root@localhost redis-5.0.14]# make
编译安装
[root@localhost redis-5.0.14]# make PREFIX=/usr/local/redis install
环境变量
[root@localhost redis-5.0.14]# ln -s /usr/local/redis/bin/* /usr/local/bin/
初始化数据库
[root@localhost redis-5.0.14]# cd utils/
[root@localhost utils]# ./install_server.sh
修改配置文件
[root@localhost utils]# vim /etc/redis/6379.conf
70行
bind 0.0.0.0
700行
appendonly yes
833行
去#号
cluster-enabled yes
841
去#号
cluster-config-file nodes-6379.conf
847
去#号
cluster-node-timeout 15000
924
yes改no 去#号
cluster-require-full-coverage no
重启redis
[root@localhost utils]# /etc/init.d/redis_6379 restart
查看运行状态,八台redis都查看 看是否成功启动
[root@localhost utils]# netstat -anpt |grep redis
在01上创建集群,任何一台都行
[root@localhost utils]# 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
验证:
登录任意一台redis查看状态
[root@localhost utils]# redis-cli -h 192.168.10.105 -p 6379 -c
192.168.10.105:6379> set name zhangsan #创建文件
查看状态
127.0.0.1:6379> cluster nodes
3813d0cdbb777d201199a5d69fffedd1b52b4430 192.168.10.101:6379@16379 master - 0 1745297107635 1 connected 0-5460
9041d75d159fa0bcfc862a947961674b9b1c5e36 192.168.10.104:6379@16379 slave 924230a965fc05ba46b8dc58cd9e1db06499429d 0 1745297109728 4 connected
1267c2de5be4c51bc0e95fe3e0fcd8264892e97e 192.168.10.105:6379@16379 slave 3813d0cdbb777d201199a5d69fffedd1b52b4430 0 1745297110782 5 connected
924230a965fc05ba46b8dc58cd9e1db06499429d 192.168.10.103:6379@16379 myself,master - 0 1745296992000 3 connected 10923-16383
f8e99e5dbb898c80cfffb9e68f42eb8422c4fa5f 192.168.10.102:6379@16379 master - 0 1745297108683 2 connected 5461-10922
1a16701a56d9238502b68b9e3aa4ec8838858cb8 192.168.10.106:6379@16379 slave f8e99e5dbb898c80cfffb9e68f42eb8422c4fa5f 0 1745297111842 6 connected
- 3813d0cdbb777d201199a5d69fffedd1b52b4430:hash算法后的id
- 192.168.10.101:6379@16379:ip以及连接端口
- master - 0:角色是否为master或者slave -是连接的master的id
- slave 3813d0cdbb777d201199a5d69fffedd1b52b4430:slave:角色 381*****:是id
- myself,master:myself指:本机 master是角色
添加节点
扩展方法一:
[root@localhost utils]# redis-cli -c -p 6379 cluster meet 192.168.10.107 6379 #指定添加的ip 端口
在其他节点查看,会发现没有分配槽
192.168.10.105:6379> cluster nodes
扩展方法二:
[root@localhost utils]# redis-cli --clusteer add-node 192.168.10.108:6379 192.168.10.107:6379
登录进去查看状态
192.168.10.105:6379> cluster nodes
108是新要添加的节点,而107是节点中集群中任意一个节点
查看会发现会发现两台都是master
删除节点
[root@localhost utils]# redis-cli
127.0.0.1:6379> flushall 清空
127.0.0.1:6379> cluster reset 重载
[root@localhost utils]# redis-cli --cluster del-node 192.168.10.108:6379 id#108的id
修改新节点为其他节点的从节点
[root@localhost utils]# redis-cli 192.168.10.108 -p 6379
登录进去
cldis-cli replicate 107的id
重新分配槽位
redis-cli --cluster rebalance --cluster-threshold 1 --cluster-use-empty-masters 192.168.10.101:6379
如果故障了出现问题,先清空数据以及重载集群在执行所出问题的命令
登录进去
127.0.0.1:6379> flushall
127.0.0.1:6379> cluster reset