Redis在主从复制模式下,每一个数据库依然存有集群中的全部数据,从而致使集群的总数据存储量受限于内存最小的服务器。node
另外,对Redis进行水平扩展比较麻烦,一般使用客户端分片来解决这个问题,由客户端决定每一个键存储到哪一个节点。但扩容时想增长新的节点就须要对数据进行手工迁移,为了保证迁移过程当中,数据的一致性,还须要将Redis暂时下线。redis
Redis在3.0版本推出了集群模式,在该模式中由Redis决定key存储在哪一个节点,以及查询时从哪一个节点查询。算法
准备8个虚拟机,安装好redis:数据库
先将前6个节点组成集群,而后在将后两个节点以扩容的形式加入到集群。bash
要使用集群,首先要开启集群的配置:服务器
cluster-enabled yes
若是由防火墙,打开16937端口(默认)测试
启动Redis后,在redis-cli终端下执行INFO cluster查询集群是否正常:ui
[root@localhost redis-5.0.7]# redis-cli 127.0.0.1:6379> INFO cluster # Cluster cluster_enabled:1
我测试的时候使用了6个节点:spa
接下来执行redis的集群命令就能够了。3d
在Redis3.0时,须要使用redis-trib.rb进行集群搭建,不然要自动手动经过命令搭建,可是在高版本的Redis中(我用的5.0),redis-cli已经实现了redis-trib.rb的功能。
在各个服务器节点上执行命令:
redis-cli --cluster create 192.168.2.104:6379 192.168.2.105:6379 192.168.2.106:6379 192.168.2.107:6379 192.168.2.108:6379 192.168.2.109:6379 --cluster-replicas 1
把6个节点的ip和端口填写上,参数--cluster-replicas 1 是表示每一个数据库拥有的从数据库个数。
执行这个命令后,集群中共有3个主数据库和3个从数据库,此致,你的集群已经搭建完毕了。能够在redis-cli终端下执行CLUSTER NODES命令查询集群的节点状态。
在理解插槽之间,先记录一下Redis若是对Key进行分区的。
Redis经过CRC16(Key) % 16384计算出一个值,根据这个值把数据存到值对应的插槽里。
Redis集群模式下一共有16384个插槽,至于为何是16384个插槽,你们能够在网上查一下看看缘由,在这里就不说了。
因此在一个集群中,全部的Key会被分配到16384个插槽中的一个插槽里。那么3个主数据库默认没人承担16384/3个插槽。
能够在redis-cli终端下执行CLUSTER SLOTS命令,查看每一个节点负责的插槽区间,Redis不要求每一个主节点负责的插槽是连续的。
对集群添加新节点时,节点类型分为主节点和从节点。
添加主节点
添加主节点作法以下,执行命令:
redis-cli --cluster add-node 192.168.2.110:6379 192.168.2.106:6379
命令的后两个参数,左边的是新节点的IP和端口(192.168.2.110:6379),右边的是集群中的任意一个节点的IP和端口(192.168.2.106:6379)。该命令会将新节点加入到集群中,并设置成主节点。
刚加入到集群中的主节点是没有负责的插槽的,执行命令:
redis-cli --cluster reshard 192.168.2.106:6379
该命令用来申请插槽,最后一个参数是集群中任意一个节点的IP和端口。执行该命令有几个交互步骤:
终端:How many slots do you want to move (from 1 to 16384) ?
填写一个数字,表明相申请多少个slot给新添加到进群的节点,我写了4096,接下来回询问:
what is the receiving node ID?
要求输入一个nodeID来接收这4096个slot,我经过CLUSTER NODES命令查询到了192.168.2.110的NodeID填写进去,接下来回询问:
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
这里是要求填入把那些节点的slots转移到新节点下,能够有2种写法:
一种是写入指定节点的nodeID,写好后输入done。
一种是写all,Redis回自动从全部节点中提取出4096个slot给新节点。
我这里写的all,回车,输入yes肯定执行。主节点添加并申请slot完毕。
添加从节点
下面为刚才添加的主节点(192.168.2.110)添加一个从节点,执行命令:
redis-cli --cluster add-node --cluster-slave --cluster-master-id 691b4cb6563da921d4d9bd191d8fa98a7cef0c23 192.168.2.111:6379 192.168.2.110:6379
后三个参数一次是:主节点NodeID,从节点IP和端口,主节点IP和端口。
这样有完成了一次扩容,添加了一个主节点和其对应的从节点,并分配给新节点4096个slot,能够经过CLUSTER NODES和CLUSTER SLOTS查询:
[root@localhost redis-5.0.7]# redis-cli 127.0.0.1:6379> CLUSTER NODES 691b4cb6563da921d4d9bd191d8fa98a7cef0c23 192.168.2.110:6379@16379 master - 0 1580832752462 9 connected 0-1364 5461-6826 10923-12287 ee1a9c31eb1571254e2679e5e84a32f7931c8b37 192.168.2.107:6379@16379 slave 3fab72ba46dd8f50fc4c665f1011c41940152385 0 1580832753000 8 connected 392006bd13d86e92d8c5dca2d89030adb7d2ed51 192.168.2.109:6379@16379 slave 435eff563051e89e7680dbc8a6146c7f4b637a36 0 1580832750445 6 connected 931f465e35513355c7043b2faba7974d1c762020 192.168.2.108:6379@16379 slave 76130efb66918698579473a592a5b9188922fa73 0 1580832749000 5 connected 435eff563051e89e7680dbc8a6146c7f4b637a36 192.168.2.105:6379@16379 master - 0 1580832751000 2 connected 6827-10922 76130efb66918698579473a592a5b9188922fa73 192.168.2.104:6379@16379 myself,master - 0 1580832751000 1 connected 1365-5460 3fab72ba46dd8f50fc4c665f1011c41940152385 192.168.2.106:6379@16379 master - 0 1580832753468 8 connected 12288-16383 f1e3cd10ed6ef51a04601f179b8446c58f2f52f1 192.168.2.111:6379@16379 slave 691b4cb6563da921d4d9bd191d8fa98a7cef0c23 0 1580832751453 9 connected
[root@localhost redis-5.0.7]# redis-cli 127.0.0.1:6379> CLUSTER SLOTS 1) 1) (integer) 0 2) (integer) 1364 3) 1) "192.168.2.110" 2) (integer) 6379 3) "691b4cb6563da921d4d9bd191d8fa98a7cef0c23" 4) 1) "192.168.2.111" 2) (integer) 6379 3) "f1e3cd10ed6ef51a04601f179b8446c58f2f52f1" 2) 1) (integer) 5461 2) (integer) 6826 3) 1) "192.168.2.110" 2) (integer) 6379 3) "691b4cb6563da921d4d9bd191d8fa98a7cef0c23" 4) 1) "192.168.2.111" 2) (integer) 6379 3) "f1e3cd10ed6ef51a04601f179b8446c58f2f52f1" 3) 1) (integer) 10923 2) (integer) 12287 3) 1) "192.168.2.110" 2) (integer) 6379 3) "691b4cb6563da921d4d9bd191d8fa98a7cef0c23" 4) 1) "192.168.2.111" 2) (integer) 6379 3) "f1e3cd10ed6ef51a04601f179b8446c58f2f52f1" 4) 1) (integer) 6827 2) (integer) 10922 3) 1) "192.168.2.105" 2) (integer) 6379 3) "435eff563051e89e7680dbc8a6146c7f4b637a36" 4) 1) "192.168.2.109" 2) (integer) 6379 3) "392006bd13d86e92d8c5dca2d89030adb7d2ed51" 5) 1) (integer) 1365 2) (integer) 5460 3) 1) "192.168.2.104" 2) (integer) 6379 3) "76130efb66918698579473a592a5b9188922fa73" 4) 1) "192.168.2.108" 2) (integer) 6379 3) "931f465e35513355c7043b2faba7974d1c762020" 6) 1) (integer) 12288 2) (integer) 16383 3) 1) "192.168.2.106" 2) (integer) 6379 3) "3fab72ba46dd8f50fc4c665f1011c41940152385" 4) 1) "192.168.2.107" 2) (integer) 6379 3) "ee1a9c31eb1571254e2679e5e84a32f7931c8b37"
当要经过redis-cli向集群中写入数据时,有可能会发生下面的错误:
[root@localhost redis-5.0.7]# redis-cli 127.0.0.1:6379> set hello world (error) MOVED 866 192.168.2.110:6379
我在192.168.2.104上的redis-cli终端执行set hello world命令,提示error,由于key通过CRC16('hello') % 16384后等于866,而866号slot所在的节点不是当前节点。能够用redis-cli -c启动终端,就能够进行测试了。
[root@localhost redis-5.0.7]# redis-cli -c 127.0.0.1:6379> set hello world!! -> Redirected to slot [866] located at 192.168.2.110:6379 OK
假如你的集群节点有一个主节点down掉了,而且这个主节点没有从节点,那么默认状况下你的集群是不可用的。
若是想在这种状况下集群使用集群,能够修改配置:
cluster-require-full-coverage no # 默认是yes
这样就能够正常使用了。
若是主节点down了,可是有至少一个从节点,那么集群就会进行故障修复,将down掉的主节点的一个从节点升级为主节点,选择哪一个从节点的过程与哨兵中选择领头哨兵的算法同样,都是基于Raft算法的。
当其中一个从数据库当选后,会经过SLAVEOF ON ONE将本身升级成主数据库,并将down掉得主数据库得slot转换给本身。
测试一下,在192.168.2.110关闭reids服务:
[root@localhost redis-5.0.7]# /etc/init.d/redis stop Stopping ... Redis stopped
在其余节点查看集群信息,会发现192.168.2.111已经升级成了master,而且负责了原来192.168.2.110所负责得slots:
127.0.0.1:6379> cluster nodes 691b4cb6563da921d4d9bd191d8fa98a7cef0c23 192.168.2.110:6379@16379 master,fail - 1580833747361 1580833745000 9 disconnected ee1a9c31eb1571254e2679e5e84a32f7931c8b37 192.168.2.107:6379@16379 slave 3fab72ba46dd8f50fc4c665f1011c41940152385 0 1580833864374 8 connected 392006bd13d86e92d8c5dca2d89030adb7d2ed51 192.168.2.109:6379@16379 slave 435eff563051e89e7680dbc8a6146c7f4b637a36 0 1580833861000 6 connected 931f465e35513355c7043b2faba7974d1c762020 192.168.2.108:6379@16379 slave 76130efb66918698579473a592a5b9188922fa73 0 1580833865382 5 connected 435eff563051e89e7680dbc8a6146c7f4b637a36 192.168.2.105:6379@16379 master - 0 1580833862000 2 connected 6827-10922 76130efb66918698579473a592a5b9188922fa73 192.168.2.104:6379@16379 myself,master - 0 1580833864000 1 connected 1365-5460 3fab72ba46dd8f50fc4c665f1011c41940152385 192.168.2.106:6379@16379 master - 0 1580833862356 8 connected 12288-16383 f1e3cd10ed6ef51a04601f179b8446c58f2f52f1 192.168.2.111:6379@16379 master - 0 1580833863365 11 connected 0-1364 5461-6826 10923-12287
下面在启动192.168.2.110的redis服务:
[root@localhost redis-5.0.7]# /etc/init.d/redis start Starting Redis server... 2706:C 05 Feb 2020 00:32:59.512 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 2706:C 05 Feb 2020 00:32:59.512 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=2706, just started 2706:C 05 Feb 2020 00:32:59.512 # Configuration loaded
查看集群信息,192.168.2.110已经变为192.168.2.111的从节点了:
127.0.0.1:6379> cluster nodes 691b4cb6563da921d4d9bd191d8fa98a7cef0c23 192.168.2.110:6379@16379 slave f1e3cd10ed6ef51a04601f179b8446c58f2f52f1 0 1580834002000 11 connected ee1a9c31eb1571254e2679e5e84a32f7931c8b37 192.168.2.107:6379@16379 slave 3fab72ba46dd8f50fc4c665f1011c41940152385 0 1580834000000 8 connected 392006bd13d86e92d8c5dca2d89030adb7d2ed51 192.168.2.109:6379@16379 slave 435eff563051e89e7680dbc8a6146c7f4b637a36 0 1580834000000 6 connected 931f465e35513355c7043b2faba7974d1c762020 192.168.2.108:6379@16379 slave 76130efb66918698579473a592a5b9188922fa73 0 1580834001773 5 connected 435eff563051e89e7680dbc8a6146c7f4b637a36 192.168.2.105:6379@16379 master - 0 1580834002780 2 connected 6827-10922 76130efb66918698579473a592a5b9188922fa73 192.168.2.104:6379@16379 myself,master - 0 1580833999000 1 connected 1365-5460 3fab72ba46dd8f50fc4c665f1011c41940152385 192.168.2.106:6379@16379 master - 0 1580834000000 8 connected 12288-16383 f1e3cd10ed6ef51a04601f179b8446c58f2f52f1 192.168.2.111:6379@16379 master - 0 1580834000764 11 connected 0-1364 5461-6826 10923-12287