目录
2. 修改配置文件 (每个节点都要配置,只有 IP 地址不同,其他都相同)
一、 Redis 集群方式
Redis 有三种模式: 分别是主从复制、哨兵模式、Cluster 。
1. 主从模式
主从复制是高可用的 Redis 的基础,哨兵和群集都是在主从复制的基础上实现搞可用的。主从复制主要实现了数据的多机备份,以及对于读写操作的负载均衡和简单的故障恢复。
2. 哨兵模式
在主从复制的基础上,哨兵实现了自动化的故障恢复。
缺陷:写操作无法负载均衡,存储能力受到单机的限制,哨兵无法对节点进行自动故障转移;在读写分离场景下,从节点故障会导致读服务不可用,需要对从节点做额外的监控,切换操作。
3. 集群模式
通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。
Redis-Cluster 是在 Redis3.0 版中推出,支持 Redis 分布式集群部署模式,采用无中心分布式架构。所有的 Redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输速度和带宽。节点的 fail 是通过集群中超过半数的节点检测失败时才生效。客户端与 Redis 节点直连,不需要中间代理层。客户端也不需要连接集群所有节点,连接集群中
任何一个可用节点即可,这样即减少了代理层,也大大提高了 Redis 集群性能。Redis Cluster 通过创建多个副本来保证数据的可靠性。每个分片都有一个主节点和多个从节点,主节点负责处理读写操作,而从节点则复制主节点的数据。当主节点发生故障时,从节点会自动切换为主节点,提供读写服务。这样可以确保即使发生节点故障,系统仍然能够继续提供服务,保证数据的高可用性。
模式 | 版本 | 优点 | 缺点 |
主从模式 | redis2.8之前 | 1、解决数据备份问题2、做到读写分离,提高服务器性能 | 1、master 故障,无法自动故障转移,需人工介入2、master 无法实现动态扩容 |
騉哨兵模式 | redis2.8级之后的模式 | 1、Master 状态监测2、master 节点故障,自动切换主从,故障自愈 3、所有 slave 从节点,随之更改新的master 节点 | 1、slave 节点下线,sentinel不会对其进行故障转移,连接从节点的客户端因为无法获取到新的可用从节点 2、master 无法实行动态扩容 |
rediscluster模式 | redis3.0 版本之后 | 1、有效的解决了 redis 在分布式方面的需求 2、遇到单机内存,并发和流量瓶颈等问题时,可采用 Cluster 方案达到负载均衡的目的 3、可实现动态扩容4、P2P 模式,无中心化5、通过 Gossip 协议同步节点信息6、自动故障转移、Slot 迁移中数据可用7、自动分割数据到不同的节点上 8、整个集群的部分节点失败或者不可达的情况下能够继续处理命令 | 1、架构比较新,最佳实践较少 3、节点发现、reshard 操作不够自动AX |
二、 集群模式简介
集群,即 Redis Cluster, 是Redis 3.0开始引入的分布式存储方案。集群由多个节点(Node)组成,Redis 的数据分布在这些节点中。集群中的节点分为主节点和从节点:只有主节点负贵读写请求和集群信息的维护:从节点只进行主节点数据和状态信息的复制。
redis 集群采用 master-slave 的方式,即1个master 节点可以包含多个 slave 节点,slave 节点主要对 master 节点的数据进行备份,如果 master 节点挂了,可以启动 salve 节点替换掉原先的 master 节点,作为新的 master 节点。redis 集群使用投票容错机制,如果集群中超过半数以上的节点投票认为某节点挂了,那么这个节点就会被认为挂掉了,所以,在设置 redis 集群时,最少的 master 节点为3个,如果每一个master 节点都添加一个 slave节点的话,搭建一个 redis 集群总共需要6个节点,即3个master 节点,3 个 slave 节点redis 集群没有统一的入口,客户端连接集群的时候,连接集群中的任意节点即可。
Redis 集群是一个由多个主从节点群组成的分布式服务集群,它具有复制、高可用和分片特性。Redis 集群不需要 sentinel 哨兵也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过 1000 个节点)。redis 集群的性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简单。redis 集群的运用主要是针对海量数据+高并发+高可用的场景。
三、 数据分片方式
对象保存到 redis 之前先经过 CRC16 哈希到一个指定的 Node 上,这个过程即 rediscluster 的分片,集群内部将所有的 key 映射到 16384个 Slot 中,集群中的每个 RedisInstance 负责其中的一部分的 Slot 的读写。集群客户端连接集群中任- Redis Instance即可发送命令,当Redis Instance 收到自己不负责的 Slot 的请求时,会将负责请求 Key所在 Slot 的 Redis Instance 地址返回给客户端,客户端收到后自动将原请求重新发往这个地址,对外部透明。一个Key 到底属于哪个S1ot由(HASH SLOT=CRC16(key)mod 16384)决定,也就是先对 key 进行哈希,然后对哈希值%16384 求余数算出槽位号。只有 master节点会被分配槽位,slave 节点不会分配槽位。
Redis Cluster 通过哈希算法将数据分散到多个节点上,实现数据的分片。每个节点负责管理一部分数据,并提供相应的读写操作。分片机制可以将数据均匀地分布在多个节点上,提高系统的并发处理能力。当某个节点发生故障时,只会影响该节点上的数据,而不会影响整个系统的可用性。
具体的分片方式有客户端分片、代理分片和Twemproxy 代理分片机制。
1. 客户端分片
客户端分片方案是将分片工作放在业务程序端。程序代码根据预先设置的路由规则,直接对多个 Redis 实例进行分布式访问。这样的好处是,群集不依赖于第三方分布式中间件,实现方法和代码都自己掌控,可随时调整,不用担心踩到坑。这实际上是一种静态分片技术,Redis 实例的增减,都得手工调整分片程序。基于此分片机制的开源产品,现在仍不多见。
这种分片机制的性能比代理式更好(少了一个中间分发环节),但缺点是升级麻烦,对研发人员的个人依赖性强,需要有较强的程序开发能力做后盾。如果主力程序员离职,可能新的负责人会选择重写一遍。所以这种方式下可运维性较差,一旦出现故障,定位和解决都得研发人员和运维人员配合解决,故障时间变长。因此这种方案,难以进行标准化运维,不太适合中小公司。
2. 代理分片
代理分片方案是将分片工作交给专门的代理程序来做。代理程序接收到来自业务程序的数据请求,根据路由规则,将这些请求分发给正确的 Redis 实例并返回给业务程序。这种机制下,一般会选用第三方代理程序(而不是自己研发)。因为后端有多个Redis 实例,所以这类程序又称为分布式中间件。这种分片机制的好处是业务程序不用关心后端Redis实例,维护起来也方便。虽然会因此带来些性能损耗,但对于 Redis 这种内存读写型应用,相对而言是能容忍的。这是比较推荐的集群实现方案。像 Twemproxy、Codis 就是基于该机制的开源产品的其中代表,应用非常广泛。
(1) Twemproxy 代理分片机制
Twemproxy 是一种代理分片机制,由 Twitter 开源。Twemproxy 作为代理,可接受来自多个程序的访问,按照路由规则,转发给后台的各个Redis 服务器,再原路返回。这个方案顺理成章地解决了单个 Redis 单实例问题。当然 Twemproxy 本身也是单点,需要用Keepalived 做高可用方案。在很长的时间内,Twemproxy 是应用范围最广、稳定性最高、最久经考验的分布式中间件。
这种分片方式无法平滑地扩容/缩容,增加了运维难度。当业务量突增需要增加 Redis服务器或业务量萎缩需要减少 Redis 服务器时,Twemproxy 都无法平滑地进行扩容或缩容等操作。
并且 Twemproxy 代理分片机制对运维操作不友好,甚至没有控制面板。由于使用了中间件代理,相比客户端直接连接服务器方式,性能上有所损耗,实测性能效果降低了 20%左右。
(2) Codis 代理分片机制
Codis 由豌豆英于 2014 年 11 月开源,基于 Go 语言和 C 语言开发,是近期涌现的.国人开发的优秀开源软件之一,现已广泛用于豌豆英的各种 Redis 业务场景。从各种压力测试来看,Codis 的稳定性符合高效运维的要求。实测 Codis 集群业务处理性能改善很多,最初集群处理数据性能要比 Twemproxy差20%左右,现在比 Twemproxy 好很多。并且 Codis具有可视化运维管理界面。因此综合方面会优于Twemproxy 很多。目前越来越多的公司选择 Codis。
Codis 引入了 Group 的概念,每个 Group包括1个 Redis Master 及至少 1个RedisSlave,这是和 Twemproxy 的区别之一。这样做的好处是,如果当前 Master 有问题则运维人员可通过 Dashboard“自助式”切换到 Slave,而不需要小心翼翼地修改程序配置文件。
为支持数据热迁移(Auto Rebalance),出品方修改了 Redis Server 源码,并称之为CodisServer。Codis 采用预先分片(Pre-Sharding)机制,事先规定分成1024个 slots(也就是说,最多能支持后端 1024 个 Codis Server),这些路由信息保存在 zookeeper 中。
3. 服务器端分片
服务器端分片是 Redis 官方的集群分片技术。Redis-Cluster 将所有 Key 映射到16384个 slot 中,集群中每个 Redis 实例负责一部分,业务程序是通过集成的Redis-Cluster 客户端进行操作。客户端可以向任一实例发出请求,如果所需数据不在该实例中,则该实例引导客户端自动去对应实例读写数据。Redis-Cluster 成员之间的管理包括节点名称、IP、端口、状态、角色等,都通过节点与之间两两通讯,定期交换信息并更新。
四、 负载均衡的实现
客户端路由: 在 Redis Cluster 中,客户端需要根据数据的键名选择正确的节点进行读写操作。Redis Cluster 使用哈希槽(hash slot)来划分数据,并将每个哈希槽映射到相应的节点上。客户端可以根据键名的哈希值,将请求发送到对应的节点上,实现负载均衡
自动迁移: Redis Cluster 具有自动迁移功能,当节点加入或离开集群时,系统会自动重新分配数据,保持各个节点上哈希槽的均衡。当节点加入集群时,系统会将一部分哈希槽从其他节点迁移到新节点上:当节点离开集群时,系统会将该节点上的哈希槽重新分配给其他节点。这种机制可以在节点数目变化时,自动调整数据的分布,实现负载均衡。
故障检测与恢复: Redis Cluster 具有故障检测和自动恢复的机制。集群中的节点会相互监控,检测节点的健康状态。当某个节点被检测到不可用时,系统会自动将该节点标记为下线,并将该节点上的哈希槽重新分配给其他节点。当节点恢复正常时,系统会将其重新加入集群,并进行数据迁移,保持数据的一致性。
Redis Cluster 通过分片和副本机制实现了数据的高可用性和负载均衡。分片机制将数据均匀地分布在多个节点上,提高了系统的并发处理能力;副本机制则保证了数据的可靠性即使发生节点故障,也能够继续提供服务。同时,Redis Cluster 通过客户端路由、自动迁移和故障检测与恢复等机制,实现了负载均衡和故障自动转移。在实际应用中,合理设计和配置 Redis Cluster,可以提高系统的性能、可靠性和可扩展性。
五、故障的处理
1. 故障转移
当从节点发现自己的主节点变为已下线(FAIL)状态时,便尝试进 Failover,以期成为新的主。
以下是故障转移的执行步骤:
- 从下线主节点的所有从节点中选中一个从节点
- 被选中的从节点执行 SLAVEOF NO NOE 命令,成为新的主节点
- 新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽全部指派给自己
- 新的主节点对集群进行广播 PONG消息,告知其他节点已经成为新的主节点
- 新的主节点开始接收和处理槽相关的请求
- 集群 slots 是否必须完整才能对外提供服务
2. 多 slave 选举
在多个 slave 情况下如果一个 master 宕机,需要基于 Raft 协议选举方式来实现的新主的选举。步骤如下:
- 当从节点发现自己的主节点进行已下线状态时,从节点会广播一条CLUSTERMSG TYPE FAILOVER AUTH REQUEST 消息,要求所有收到这条消息,并且具有投票权的主节点向这个从节点投票。
- 如果一个主节点具有投票权,并且这个主节点尚未投票给其他从节点,那么主节点将向要求投票的从节点返回一条,CLUSTERMSG TYPE FAILOVER AUTH ACK 消息,表示这个主节点支持从节点成为新的主节点。
- 每个参与选举的从节点都会接收CLUSTERMSG TYPE FAILOVER AUTH ACK 消息,并根据自己收到了多少条这种消息来统计自己获得了多少主节点的支持。
- 如果集群里有N个具有投票权的主节点,那么当一个从节点收集到大于等于集群 N/2+1张支持票时,这个从节点就成为新的主节点。
- 如果在一个选举周期没有从能够收集到足够的支持票数,那么集群进入一个新的选举周期,并再次进行选主,直到选出新的主节点为止。
六、 Redis 群集部署
1. 安装 Redis (每个节点都要安装)
关闭防火墙 & SELinux:
systemctl stop firewalld setenforce 0
安装编译依赖:
dnf -y install gcc
Redis 编译安装
tar xzf redis-5.0.14.tar.gz cd redis-5.0.14 make # 编译(需确保依赖完整,否则报错)
初始化服务:
cd utils/ ./install_server.sh # 交互式配置,默认选项即可(端口、日志、PID路径等)
2. 修改配置文件 (每个节点都要配置,只有 IP 地址不同,其他都相同)
# 网络与运行模式 bind 0.0.0.0 # 允许所有IP访问(实验环境,生产需限制) protected-mode yes # 配合 bind 使用,避免安全风险 port 6379 # 监听端口 daemonize yes # 后台运行 pidfile /var/run/redis_6379.pid # PID 文件路径 logfile /var/log/redis_6379.log # 日志路径 # 持久化(可选增强) appendonly yes # 开启 AOF 持久化 # 集群关键配置(取消注释并修改) cluster-enabled yes # 启用集群模式 cluster-config-file nodes-6379.conf # Redis 自动维护的集群配置文件(勿手动改) cluster-node-timeout 15000 # 节点超时时间(15秒,超时判定为宕机) cluster-require-full-coverage no # 槽位未全部分配时仍提供服务(必改,否则集群易挂) /etc/init.d/redis_6379 restart # 重启服务 netstat -antp | grep 6379 # 检查 6379 端口是否监听(应显示 LISTEN 状态)
3. 创建 Redis 群集
redis-cli --cluster create \ --cluster-replicas 1 \ # 每个主节点对应 1 个从节点 192.168.10.101:6379 192.168.10.102:6379 192.168.10.103:6379 \ # 3 主节点 192.168.10.104:6379 192.168.10.105:6379 192.168.10.106:6379 # 3 从节点
- 按提示输入
yes
确认 槽位分配(Redis 自动均分 16384 个槽位到主节点)。
4. 测试群集
写入
redis-cli -h 192.168.10.106 -p 6379 -c # -c 启用集群模式(自动重定向) 192.168.10.106:6379> set centos 7.3 # 写入数据 192.168.10.106:6379> quit
读取
redis-cli -h 192.168.10.105 -p 6379 -c 192.168.10.105:6379> get centos # 验证数据同步(应返回 "7.3") 192.168.10.105:6379> quit
5. 集群信息查看
节点拓扑(任意节点,进入 redis-cli
后执行):
redis-cli -h 192.168.10.106 -p 6379 -c 192.168.10.106:6379> cluster nodes # 列出所有节点(角色、槽位、主从关系等)
健康检查:
redis-cli --cluster check 192.168.10.101:6379 # 检查指定主节点的集群状态
6. 添加节点
方法 1:cluster meet
命令(在现有集群节点执行):
redis-cli -c -p 6379 cluster meet 192.168.10.107 6379 # 加入集群,默认角色为 master
方法 2:--cluster add-node
命令:
redis-cli --cluster add-node 192.168.10.108:6379 192.168.10.101:6379 # 10.101 为现有节点
7. 删除节点
步骤 1:清除槽位 & 重置状态
redis-cli -h 192.168.10.108 -p 6379 192.168.10.108:6379> flushall # 清空数据 192.168.10.108:6379> cluster reset # 重置集群状态 192.168.10.108:6379> quit
步骤 2:删除节点
redis-cli --cluster del-node 192.168.10.108:6379 <节点ID> # 节点 ID 可通过 `cluster nodes` 查询
8. 修改新节点为其他节点的从节点
先通过 cluster meet
或 add-node
加入集群,再执行:
redis-cli -h 192.168.10.108 -p 6379 192.168.10.108:6379> cluster replicate <10.107的节点ID> # 成为 10.107 的从节点
9. 重新分配槽位
自动平衡(平衡集群负载,任意节点执行):
redis-cli --cluster rebalance \ --cluster-threshold 1 \ --cluster-use-empty-masters \ 192.168.10.101:6379 # 指定现有主节点,Redis 自动识别其他节点
手动分配(示例:给无槽位的主节点分配 0~5460 槽位)
redis-cli -h 127.0.0.1 -p 6379 CLUSTER ADDSLOTS {0..5460} # 按范围分配槽位
七、 集群排错思路
1. 槽位占用错误
每个节点执行:
redis-cli -h <节点IP> -p 6379 > flushall # 清空旧数据 > cluster reset # 重置集群状态 > quit rm -f /var/lib/redis/6379/nodes-6379.conf # 删除旧集群配置文件
重启服务后,重新创建集群。
2. 启动失败
直接通过配置文件启动:
redis-server /etc/redis/6379.conf
关闭服务(指定 IP,而非 127.0.0.1):
redis-cli -h <本机IP> -p 6379 shutdown
3. 集群创建卡住
在所有 slave 节点 执行
redis-cli -h <slaveIP> -p 6379 > cluster meet <主节点IP> 6379 # 主动加入主节点,触发集群同步