redis cluster集群是由多个主从节点群组成的分布式服务器集群,具有复制、高可用和分片特性。不需要哨兵也能完成节点的移除和故障转移功能。
需要将每个节点设置成集群模式,这种集群没有中心节点,可以线程扩展高达1000个节点。
密钥分配模型
Redis Cluster集群数据分片没有使用一致哈希,而是使用哈希槽。redis集群有16384个哈希槽,要计算哈希槽,只需要给定键的CRC16取模16384。
集群中的每个节点都负责哈希槽的子集,这样可以轻松添加和删除集群中的节点
集群总线
一个服务于客户端的TCP端口,如6379
一个用于集群总线(客户端端口加10000),16379:用于故障检测、配置更新、故障转移。
节点与节点的通信仅使用集群总线和集群总线协议进行。
如果两个端口没有开放,则集群不能正常工作
redis cluster集群搭建
redis cluster集群至少需要三个master节点,我们这里搭建3个master,且给每个master一个slave节点。这里搭建伪分布式都在一台上,端口8001到8006。
1、创建文件夹redis-cluster,在redis-cluster下面创建6个文件夹 8001到8006
mkdir -p /opt/redis-cluster
mkdir 8001 8002 8003 8004 8005 8006
2、把redis.conf配置文件复制到8001,并修改如下
daemonize yes
port 8001
bind 127.0.0.1
dir /opt/redis-cluster/8001/
cluster-enabled yes
cluster-config-file nodes-8001.conf
cluster-node-timeout 5000
appendonly yes
其他文件修改对应端口就行
sed 's/8001/8002/g' /opt/redis-cluster/8001redis.conf > /opt/redis-cluster/8002/redis.conf
然后启动8001到8006端口的redis
redis-server /usr/local/redis-cluster/800*/redis.conf
3、设置集群
启动完成之后需要设置集群模式,有以下方式
①原生搭建
meet
cluster meet ip port
指派槽( 0到16383)
根据crc16 算法 算出key槽位
cluster keyslot
cluster addslots slot(槽位下标)
分配主从
cluster replicate node-id
②redis提供的rb脚本
如果要使用ruby需要首先安装
apt-get install ruby rubygems
gem install redis --version 3.0.0
然后在redis的安装目录下执行 redis-trib.rb命令创建整个redis集群,槽位可以按照指引完成
./redis-trib.rb create --replicas 1 127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 127.0.0.1:8004 127.0.0.1:8005 127.0.0.1:8006
③redis-cli --cluster命令
redis5.0之后可以使用,槽位也可以按照指引完成分配
redis-cli --cluster create 192.127.0.0.1:8001 127.0.0.1:8002 127.0.0.1:8003 192.168.0.104:8004 127.0.0.1:8005 127.0.0.1:8006 --cluster-replicas 1
--cluster-replicas值代表master与slave的比例,如果是1则master有三台slave有三台8004、8005、8006是slave随机对应8001、8002、8003端口
4、验证集群
连接任意客户端/usr/local/redis/bin/redis-cli -c -h 127.0.0.1 -p 8002
验证cluster info(查看集群信息)、cluster nodes(查看节点列表)、及数据添加测试
redis 127.0.0.1:8002> set hello world
-> Redirected to slot [866] located at 127.0.0.1:8001
OK
如果需要关闭,则一个一个关闭redis-cli -c -h 127.0.0.1 -p 800* shutdown
集群伸缩
扩容集群
1、准备新节点
如8007、8008端口节点。创建过程与其他端口相同
2、加入集群
使用redis-cli 并指定主从
add-node 新节点ip 端口 已存在节点ip 端口 --cluster-slave --cluster-master-id masterID
使用原生命令 语法:cluster meet ip port cluster replicate node-id
3、迁移槽和数据
槽迁移 redis-cli --cluster reshard 127.0.0.1:8001
迁移数据:根据提示要分配多少槽、接收节点ID、all/done
添加从节点
缩容集群
1、下线迁移槽
redis-cli --cluster reshard --cluster-from 迁出节点ID --cluster-to 接收槽节点ID --cluster-slots 迁出槽数量 已存在节点ip 端口
2、忘记并关闭节点
redis-cli --cluster del-node 存在节点IP:端口 要删除的节点ID
故障转移
与哨兵类似,故障发现不依赖哨兵
故障恢复:
1、检查每个从节点与主节点断开时间
2、选择偏移量最大的并替换主节点
slaveof no one变为主节点,撤销之前主节点槽位给新主节点,并向集群广播已经替换故障节点
重定向和重新分片
moved重定向:发送命令时,经过crc16算法,客户端没有这个数字范围。需要捕获异常
asx重定向:发送命令时,正在迁移槽位
moved移动重定向
Redis客户端可以向集群的每个节点发送查询,如果这个hash槽由这个节点服务则查询被简单处理。否则,节点将会检查其内部哈希槽到节点的映射,并通过MOVED错误回复客户端。如下面示例所示,仅做参考:
GET x
-MOVED 3999 127.0.0.1:7001
错误包括键的哈希槽(3999)和可以为查询提供服务的ip:port。在收到MOVED重定向后,使用cluster nodes或cluster slots命令刷新整个客户端集群布局,遇到这种情况,可能重新配置了多个插槽,而不仅仅一个,因此尽快更新比较好
ASK重定向
当迁移槽时,可以将插槽设置:
migrating时,表示该节点将接受与该哈希槽有关的所有查询,但是仅当所讨论的键存在是,否则该查询将使用ask重定向转发到迁移目标节点
importing时,则该节点接受与该哈希槽有关的所有查询,前提是请求之前带有ASKING命令。如果客户端未提供命令,则查询会通过-MOVED重定向错误重定向到实际的哈希槽所有者
假如:哈希槽8 从A移动到B
moved意味着我们认为哈希槽由另一个节点永久提供。所以,ASK意味着仅将下一个查询发送到指定节点。这么做的原因是因为哈希槽的查询可能在迁移前的节点B仍然存在,因此始终希望客户端尝试之前的节点A,然后需要时尝试迁移后的节点。
如果客户端查询之前发送asking命令,则节点B将仅接受设置为importing的插槽查询
一旦哈希槽8迁移完成,A将发送moved消息,且客户端永久映射新的ip和端口
总结
redis cluster集群是高可用集群,使用哈希槽分片可以轻松添加或删除节点。
解决了哨兵模式单机存储受限问题、及写操作的负载均衡
可以解决缓存雪崩问题