Redis哨兵集群模式,每个节点都保存全量同步数据,冗余的数据比较多。从Redis3.0开始官方推出了RedisCluster集群模式 ,采用分片集群模式,可以减少冗余数据,但也提高了集群成本,RedisCluster集群最大的优点:动态扩容、缩容
。
1. RedisCluster集群的原理
- Redis主节点之间会互相通信,两两相连,因此RedisCluster集群无中心节点(无主模型)
- RedisCluster集群的主节点内置了类似Redis Sentinel的节点故障检测功能和自动选举机制,因此不在需要sentinel服务,当一个主节点出现故障时,由其他主节点来负责他的从节点替换
- 当过半的主节点进程挂掉,依据过半机制,集群将无法做主从切换 ,且不能对外提供服务
- RedisCluster集群采用hash槽的概念,整个数据库分为16384个槽位slot,这些槽位分配到Redis主节点中(一般是均分,也可自己手动分配),数据根据key的槽位计算公式
slot_number=crc16(key)%16384
分配到各个槽中,(crc16为16位的循环冗余校验和函数) - 其中任意一个节点主从都挂掉,将不能对外提供服务,因hash槽不完整,数据也就不完整
- 由于Redis集群无中心节点,在向集群发送请求时,会有Redirect转向过程,具体如下:
-
- 客户端请求会发给任意主节点(数据到达服务端时已计算好属于哪个槽位)
-
- 主节点只会处理自己负责槽位的命令请求,其它槽位的命令请求,该主节点会返回客户端一个转向错误
-
- 客户端根据错误中包含的地址和端口重新向正确的负责的主节点发起命令请求
-
2. RedisCluster集群搭建
以最简单的为例,分别搭建3组节点,每组1主2从,如上图示。因机器有限,3组节点分别搭在3个虚拟机中,3台虚拟机IP:192.168.100.51、192.168.100.52、192.168.100.53
,每组节点端口:6381、6382、6383
2.1 配置文件
配置文件基本和原来的一样,主要区别是要开启CLuster集群模式,
- 注释掉bind的ip:
#
127.0.0.1
- 关闭保护模式,使能远程访问:
protected-mode no
- 修改端口:
port 6381
- 开启后台守护进程运行:
daemonize yes
- 修改pid文件为6381:
pidfile /var/run/redis_6381.pid
- 日志输出到文件,默认双引号输出到控制台:
logfile /usr/local/redis/logs/6381.log
- 修改数据库文件:
dbfilename dump_6381.rdb
- 修改数据库目录:
dir ../data/
- 放开密码注释,添加密码:
requirepass 123456
- 开启集群模式,每个节点都开启
cluster-enabled yes # 启动集群模式(去掉注释)
cluster-config-file nodes-6381.conf # 集群节点信息文件
cluster-node-timeout 10000
masterauth "123456" # 添加密码,没有可以不设置,要是有,所有节点密码要一致
2.2 启动集群节点
3台虚拟机,9个node节点分别启动
cd /usr/local/redis/bin
./redis-server ../redis_6381.conf
./redis-server ../redis_6382.conf
./redis-server ../redis_6383.conf
ps aux | grep redis
2.3 创建集群并将节点加入集群
因为搭建在了 3台虚拟主机上,所以要先关闭防火墙
# 51、52、53三台虚拟机都运行一遍,关闭防火墙
systemctl stop firewalld # 关闭防火墙
systemctl disable firewalld # 取消防火墙开机启动
用命令将9台节点组成集群,在一台机器运行就行
-
--cluster-replicas 2
副本数量为2 -
-a 123456
用来写密码的
redis-cli --cluster create 192.168.100.51:6381 192.168.100.51:6382 192.168.100.51:6383 192.168.100.52:6381 192.168.100.52:6382 192.168.100.52:6383 192.168.100.53:6381 192.168.100.53:6382 192.168.100.53:6383 --cluster-replicas 2 -a 123456
上图给出了自动分配的槽位和主从节点,槽位是均分的,主从搭配也比较合理,主节点在一台机子,2个从节点分别在另外2台机子。感觉分配没有问题,输入
yes
就可以继续了。
注意:槽位只在主节点有,从节点中没有
2.4 客户端连接集群
连接集群和单机基本一样,但需要注意2点:
- 加入
-c
参数,表示连接集群 - 在连接时用
-a
加入密码,不用auth
,不然在Redirected to
时会报错
redis-cli -p 6381 -c -a 123456
连接以后用cluster nodes
命令查看节点信息,测试写入
2.5 测试集群故障转移
杀死52上的主节点,等几秒钟,查看集群情况
然后重启,在查看集群情况,如下图:
3. 集群缩容
集群减少一组主从节点,现在有3组,先把51:6381这一组去掉吧。
3.1 直接删除从节点
192.168.100.51:6381
的从节点分别是192.168.100.52:6382
,192.168.100.53:6382
,直接删除这2个,注意操作时都用到node id
redis-cli --cluster del-node 192.168.100.52:6382 bf5e9fad5be3fba1ee4a719377a6b98c9a5eab76 -a 123456
redis-cli --cluster del-node 192.168.100.53:6382 91e2e24781143c7dfeab21b78c79558420b6ed37 -a 123456
3.2 主节点槽位迁移
主节点192.168.100.51:6381
的slots转移到其他1个或多个节点,看硬件配置分配,这里就直接都给192.168.100.53:6381
吧。
redis-cli --cluster reshard 192.168.100.51:6381 --cluster-from 9ae390a9a5c19af0c4f3adb73439ee5b1d6c7be8 --cluster-to ef710a1daeb95613b7a39216010b80b80e428a60 --cluster-slots 5461 -a 123456
3.3 删除主节点
删除之前,先查看一遍节点信息,确认槽位已经转移,再删除
- 删除主节点
redis-cli --cluster del-node 192.168.100.51:6381 9ae390a9a5c19af0c4f3adb73439ee5b1d6c7be8 -a 123456
4. 集群扩容
集群扩容肯定是增加一组,即主从一块增加
4.1 新增主节点
启动好要增加的服务节点,新增主节点,命令中第2个地址是现在集群中任一个node节点的,注意不要搞错
redis-cli --cluster add-node 192.168.100.51:6381 192.168.100.53:6381 -a 123456
4.2 分配槽位
redis-cli --cluster reshard 192.168.100.51:6381 --cluster-from ef710a1daeb95613b7a39216010b80b80e428a60 --cluster-to 5ebfea2aa2bb2477d43ca212d4313f8f06355fdb --cluster-slots 5461 -a 123456
4.3 添加从节点
从节点有2个,分别添加
redis-cli --cluster add-node 192.168.100.52:6382 192.168.100.51:6381 --cluster-slave --cluster-master-id 5ebfea2aa2bb2477d43ca212d4313f8f06355fdb -a 123456
redis-cli --cluster add-node 192.168.100.53:6382 192.168.100.51:6381 --cluster-slave --cluster-master-id 5ebfea2aa2bb2477d43ca212d4313f8f06355fdb -a 123456
5. RedisCluster集群总结
-
- Redis集群是一个由多个节点组成的分布式服务集群,它具有复制、高可用和分片特性
-
- Redis的集群没有中心节点,并且带有复制和故障转移特性,这可用避免单个节点成为性能瓶颈,或者因为某个节点下线而导致整个集群下线
-
- 集群中的主节点负责处理槽(储存数据),而从节点则是主节点的复制品
-
- Redis集群将整个数据库分为16384个槽,数据库中的每个键都属于16384个槽中的其中一个
-
- 集群中的每个主节点都可以负责0个至16384个槽,当16384个槽都有节点在负责时,集群进入上线状态,可以执行客户端发送的数据命令
-
- 主节点只会执行和自己负责的槽有关的命令,当节点接收到不属于自己处理的槽的命令时,它将会处理指定槽的节点的地址返回给客户端,而客户端会向正确的节点重新发送