Redis集群是一个提供在多个Redis节点之间共享数据的程序集。它并不像Redis主从复制模式那样只提供一个master节点提供写服务,而是会提供多个master节点提供写服务,每个master节点中存储的数据都不一样,这些数据通过数据分片的方式被自动分割到不同的master节点上。
我们一般要实现一个Redis集群,可以有三种方式:客户端实现、Proxy代理层、服务端实现。
我们通过代码的实现方式,实现集群访问,如下图所示:
这样的访问方式都通过代码来维护集群以及访问路径,可是这样的方式 维护难度大,也不支持动态扩容,因为一切都以代码实现访问规划。
如图所示:
我们在Redis和我们的客户端之间新加了一层Proxy,我们通过Proxy去规划访问,这样我们在代码层面以及Redis部署层面就无需处理,而且市面上也提供了这样的中间件,如Codis(国产)、Twemproxy。我们看下Codis的架构图,就可以知道这个插件是如何工作的,如图所示:
可见Codis是一个很完善的集群管理实现,我们可以不关心具体分片规则,程序开发容易简单,可是这样也有它的一些缺点:
Codis的GitHub地址:https://github.com/CodisLabs/codis
服务端的实现方式就是标准的集群(分区分片)模式,RedisCluster是Redis在3.0版本后推出的分布式解决方案。
Cluster模式实现了Redis的分布式存储,即每台节点存储不同的内容,来解决在线扩容的问题。如图:
RedisCluster采用无中心结构,它的特点如下:
为了保证集群的高可用,每个master节点下面还需要添加至少1个slave节点,这样当某个master节点发生故障后,可以从它的slave节点中选举一个作为新的master节点继续提供服务。不过当某个master节点和它下面所有的slave节点都发生故障时,整个集群就不可用了。这样就组成了下图中的结构模式:
为什么需要三主三从?
因为内部存在一个投票机制,节点的有效性是需要靠投票的,一个节点无法给自己投票,两个节点互相都连不上,A=>B,B=>A互相都说对方挂了没有定论.三个节点才能满足投票的需求。
Cluster模式的具体工作机制:
Cluster模式集群节点最小配置6个节点(3主3从,因为需要半数以上),其中主节点提供读写操作,从节点作为备用节点,不提供请求,只作为故障转移使用。关于集群中的涉及动态选举的机制,请参考地址:Raft
既然Redis集群中的数据是通过哈希槽的方式分开存储的,那么集群中每个节点都需要知道其他所有节点的状态信息,包括当前集群状态、集群中各节点负责的哈希槽、集群中各节点的master-slave状态、集群中各节点的存活状态等。Redis集群中,节点之间通过建立TCP连接,使用gossip协议来传播集群的信息。如下图:
所谓gossip协议,指的是一种消息传播的机制,类似人们传递八卦消息似的,一传十,十传百,直至所有人都知道这条八卦内容。Redis集群中各节点之间传递消息就是基于gossip协议,最终达到所有节点都会知道整个集群完整的信息。gossip协议有4种常用的消息类型:PING、PONG、MEET、FAIL。
Redis客户端可以向Redis集群中的任意master节点发送操作指令,可以向所有节点(包括slave节点)发送查询指令。当Redis节点接收到相关指令时,会先计算key落在哪个哈希槽上(对key进行CRC16校验后再对16384取模),如果key计算出的哈希槽恰好在自己节点上,那么就直接处理指令并返回结果,如果key计算出的哈希槽不在自己节点上,那么当前节点就会查看它内部维护的哈希槽与节点ID之间的映射关系,然后给客户端返回一个MOVED错误:MOVED [哈希槽] [节点IP:端口]。这个错误包含操作的key所属的哈希槽和能处理这个请求的Redis节点的IP和端口号,例如“MOVED 3999 127.0.0.1:6379”,客户端需要根据这个信息重新发送查询指令到给定的IP和端口的Redis节点。
优点:
缺点:
集群内部采用Gossip协议(谣言传播)协同自动化修复集群的状态,但Gossip有消息延时和消息冗余的问题,在集群节点数量过多的时候,节点之间需要不断进行PING/PANG通讯,不必须要的流量占用了大量的网络资源。
Redis Cluster可以进行节点的动态扩容缩容,在扩缩容的时候,就需要进行数据迁移。而Redis 为了保证迁移的一致性, 迁移所有操作都是同步操作,执行迁移时,两端的 Redis 均会进入时长不等的 阻塞状态。对于小 Key,该时间可以忽略不计,但如果一旦 Key 的内存使用过大,严重的时候会接触发集群内的故障转移,造成不必要的切换.
Gossip 的缺陷 - 消息的延迟 由于 Gossip 协议中,节点只会随机向少数几个节点发送消息,消息最终是通过多 个轮次的散播而到达全网的。 因此使用 Gossip 协议会造成不可避免的消息延迟。不适合用在对实时性要求较高 的场景下。
消息冗余 Gossip 协议规定,节点会定期随机选择周围节点发送消息,而收到消息的节点也会重复该步骤。 因此存在消息重复发送给同一节点的情况,造成了消息的冗余,同时也增加了收到消息的节点的处理压力。 而且,由于是定期发送而且不反馈,因此即使节点收到了消息,还是会反复收到重复消息,加重了消息的冗余。
首先我们复制6份redis.conf配置文件,分别命名为redis7001.conf、redis7002.conf、redis7003.conf、redis7004.conf、redis7005.conf、redis7006conf,存放在自己想要放的地方。
并按照下列配置信息修改配置文件:
#修改成自己对应的端口号
port
#指定了记录日志的文件。
logfile
#数据目录,数据库的写入会在这个目录。rdb、aof文件也会写在这个目录
dir
#是否开启集群
cluster-enabled
#集群配置文件的名称,每个节点都有一个集群相关的配置文件,持久化保存集群的信息。
#这个文件并不需要手动配置,这个配置文件由Redis生成并更新,每个Redis集群节点需要一个单独的配置文件,请确保与实例运行的系统中配置文件名称不冲突(建议配对应端口号)
cluster-config-file nodes-6379.conf
#节点互连超时的阀值。集群节点超时毫秒数
cluster-node-timeout 5000
#默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。
#但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性。
#Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。
appendonly
appendonly yes
protected-mode no #保护模式 yes改为no
#bind 127.0.0.1 #注释或者去掉这个
daemonize yes #用来指定redis是否要用守护线程的方式启动,yes表示后台启动
执行命令分别启动所有节点,如:
/Volumes/work/redis-5.0.8/src/redis-server
/Volumes/work/redis-5.0.8/conf/7001/redis7001.conf
/Volumes/work/redis-5.0.8/src/redis-server
/Volumes/work/redis-5.0.8/conf/7002/redis7002.conf
/Volumes/work/redis-5.0.8/src/redis-server
/Volumes/work/redis-5.0.8/conf/7003/redis7003.conf
/Volumes/work/redis-5.0.8/src/redis-server
/Volumes/work/redis-5.0.8/conf/7004/redis7004.conf
/Volumes/work/redis-5.0.8/src/redis-server
/Volumes/work/redis-5.0.8/conf/7005/redis7005.conf
/Volumes/work/redis-5.0.8/src/redis-server
/Volumes/work/redis-5.0.8/conf/7006/redis7006.conf
可以查看到进程:
192:conf houjing$ ps -ef |grep redis
501 43005 1 0 5:46上午 ?? 0:00.20 /Volumes/work/redis-5.0.8/src/redis-server *:7001 [cluster]
501 43018 1 0 5:47上午 ?? 0:00.02 /Volumes/work/redis-5.0.8/src/redis-server *:7002 [cluster]
501 43020 1 0 5:47上午 ?? 0:00.02 /Volumes/work/redis-5.0.8/src/redis-server *:7003 [cluster]
501 43022 1 0 5:47上午 ?? 0:00.02 /Volumes/work/redis-5.0.8/src/redis-server *:7004 [cluster]
501 43024 1 0 5:47上午 ?? 0:00.02 /Volumes/work/redis-5.0.8/src/redis-server *:7005 [cluster]
501 43026 1 0 5:47上午 ?? 0:00.01 /Volumes/work/redis-5.0.8/src/redis-server *:7006 [cluster]
执行命令创建集群:
/Volumes/work/redis-5.0.8/src/redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
--cluster-replicas 1 # 1表示每个主节点至少一个备份
可以得到如下结果:
192:conf houjing$ /Volumes/work/redis-5.0.8/src/redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:7005 to 127.0.0.1:7001
Adding replica 127.0.0.1:7006 to 127.0.0.1:7002
Adding replica 127.0.0.1:7004 to 127.0.0.1:7003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 4c7fcd06c55ceec27b5bbc450b99159282e7783e 127.0.0.1:7001
slots:[0-5460] (5461 slots) master
M: d7a0d77d2f0fa05ccf4a14e379b52044b212607e 127.0.0.1:7002
slots:[5461-10922] (5462 slots) master
M: 6494df31d4ed564d80947c9d39369cc7cfb6c0e6 127.0.0.1:7003
slots:[10923-16383] (5461 slots) master
S: 9d6d78888e579442b209fca95af13b6ece4810b6 127.0.0.1:7004
replicates 6494df31d4ed564d80947c9d39369cc7cfb6c0e6
S: 8891bfe505da42298be048364ed003b83dc52139 127.0.0.1:7005
replicates 4c7fcd06c55ceec27b5bbc450b99159282e7783e
S: 981ad9769245c140c0bd9ee239472dc6e2cb07eb 127.0.0.1:7006
replicates d7a0d77d2f0fa05ccf4a14e379b52044b212607e
Can I set the above configuration? (type 'yes' to accept): yes 此处输入yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
...
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: 4c7fcd06c55ceec27b5bbc450b99159282e7783e 127.0.0.1:7001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 981ad9769245c140c0bd9ee239472dc6e2cb07eb 127.0.0.1:7006
slots: (0 slots) slave
replicates d7a0d77d2f0fa05ccf4a14e379b52044b212607e
M: 6494df31d4ed564d80947c9d39369cc7cfb6c0e6 127.0.0.1:7003
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 9d6d78888e579442b209fca95af13b6ece4810b6 127.0.0.1:7004
slots: (0 slots) slave
replicates 6494df31d4ed564d80947c9d39369cc7cfb6c0e6
M: d7a0d77d2f0fa05ccf4a14e379b52044b212607e 127.0.0.1:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 8891bfe505da42298be048364ed003b83dc52139 127.0.0.1:7005
slots: (0 slots) slave
replicates 4c7fcd06c55ceec27b5bbc450b99159282e7783e
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
可以执行命令 ./redis-cli -c -p 7001 进行登录,然后查看集群信息以及slot分配信息:
192:src houjing$ ./redis-cli -c -p 7001
127.0.0.1:7001> cluster nodes
981ad9769245c140c0bd9ee239472dc6e2cb07eb 127.0.0.1:7006@17006 slave d7a0d77d2f0fa05ccf4a14e379b52044b212607e 0 1586210070424 6 connected
4c7fcd06c55ceec27b5bbc450b99159282e7783e 127.0.0.1:7001@17001 myself,master - 0 1586210069000 1 connected 0-5460
6494df31d4ed564d80947c9d39369cc7cfb6c0e6 127.0.0.1:7003@17003 master - 0 1586210071437 3 connected 10923-16383
9d6d78888e579442b209fca95af13b6ece4810b6 127.0.0.1:7004@17004 slave 6494df31d4ed564d80947c9d39369cc7cfb6c0e6 0 1586210069416 4 connected
d7a0d77d2f0fa05ccf4a14e379b52044b212607e 127.0.0.1:7002@17002 master - 0 1586210070000 2 connected 5461-10922
8891bfe505da42298be048364ed003b83dc52139 127.0.0.1:7005@17005 slave 4c7fcd06c55ceec27b5bbc450b99159282e7783e 0 1586210070000 5 connected
可以根据以上得出总共有3个master节点,每个节点有一个slave节点,三个master节点分别分配了0-5460、5461-10922、10923-16383三个slot范围,7001这个master节点的slave节点为7005节点,其id为4c7fcd06c55ceec27b5bbc450b99159282e7783e。
添加数据,可以看到数据会根hash然后存到对应的slot槽,也就是存到slot槽对应的节点上,如下所示:
127.0.0.1:7001> set 789 789
-> Redirected to slot [11123] located at 127.0.0.1:7003
OK
127.0.0.1:7003> set 123 123
-> Redirected to slot [5970] located at 127.0.0.1:7002
OK
127.0.0.1:7002> set 365 365
-> Redirected to slot [5424] located at 127.0.0.1:7001
OK
当然每个节点也只有自己的那部分数据:
127.0.0.1:7001> keys *
1) "365"
我们通过手动杀掉节点7001的进程:
192:bin houjing$ kill 43005
192:bin houjing$ ps -ef|grep redis
501 43018 1 0 5:47上午 ?? 0:03.91 /Volumes/work/redis-5.0.8/src/redis-server *:7002 [cluster]
501 43020 1 0 5:47上午 ?? 0:03.94 /Volumes/work/redis-5.0.8/src/redis-server *:7003 [cluster]
501 43022 1 0 5:47上午 ?? 0:03.95 /Volumes/work/redis-5.0.8/src/redis-server *:7004 [cluster]
501 43024 1 0 5:47上午 ?? 0:03.92 /Volumes/work/redis-5.0.8/src/redis-server *:7005 [cluster]
501 43026 1 0 5:47上午 ?? 0:03.91 /Volumes/work/redis-5.0.8/src/redis-server *:7006 [cluster]
然后查看集群信息:
127.0.0.1:7002> cluster nodes
8891bfe505da42298be048364ed003b83dc52139 127.0.0.1:7005@17005 master - 0 1586210953749 7 connected 0-5460
9d6d78888e579442b209fca95af13b6ece4810b6 127.0.0.1:7004@17004 slave 6494df31d4ed564d80947c9d39369cc7cfb6c0e6 0 1586210953547 4 connected
981ad9769245c140c0bd9ee239472dc6e2cb07eb 127.0.0.1:7006@17006 slave d7a0d77d2f0fa05ccf4a14e379b52044b212607e 0 1586210952000 6 connected
d7a0d77d2f0fa05ccf4a14e379b52044b212607e 127.0.0.1:7002@17002 myself,master - 0 1586210952000 2 connected 5461-10922
6494df31d4ed564d80947c9d39369cc7cfb6c0e6 127.0.0.1:7003@17003 master - 0 1586210952538 3 connected 10923-16383
4c7fcd06c55ceec27b5bbc450b99159282e7783e 127.0.0.1:7001@17001 master,fail - 1586210920633 1586210919825 1 disconnected
可以看到原先7001节点断开连接,其slave节点7005顶替了7001节点,变成了master节点,并继承了原先7001节点的slot槽。
当我们重新启动7001节点后,7001节点便作为7005的slave节点重新上线:
127.0.0.1:7002> cluster nodes
8891bfe505da42298be048364ed003b83dc52139 127.0.0.1:7005@17005 master - 0 1586211138837 7 connected 0-5460
9d6d78888e579442b209fca95af13b6ece4810b6 127.0.0.1:7004@17004 slave 6494df31d4ed564d80947c9d39369cc7cfb6c0e6 0 1586211138331 4 connected
981ad9769245c140c0bd9ee239472dc6e2cb07eb 127.0.0.1:7006@17006 slave d7a0d77d2f0fa05ccf4a14e379b52044b212607e 0 1586211139548 6 connected
d7a0d77d2f0fa05ccf4a14e379b52044b212607e 127.0.0.1:7002@17002 myself,master - 0 1586211138000 2 connected 5461-10922
6494df31d4ed564d80947c9d39369cc7cfb6c0e6 127.0.0.1:7003@17003 master - 0 1586211139000 3 connected 10923-16383
4c7fcd06c55ceec27b5bbc450b99159282e7783e 127.0.0.1:7001@17001 slave 8891bfe505da42298be048364ed003b83dc52139 0 1586211137522 7 connected
由于我们Redis集群是有能力限制的,当不能满足当下要求的时候,就需要进行扩容,这事就涉及到水平扩展,我们先增加两份配置文件redis7007.conf、redis7008.conf,并创建两个节点并启动:
192:conf houjing$ /Volumes/work/redis-5.0.8/src/redis-server /Volumes/work/redis-5.0.8/conf/7007/redis7007.conf
192:conf houjing$ /Volumes/work/redis-5.0.8/src/redis-server /Volumes/work/redis-5.0.8/conf/7008/redis7008.conf
192:conf houjing$ ps -ef |grep redis
501 43018 1 0 5:47上午 ?? 0:06.27 /Volumes/work/redis-5.0.8/src/redis-server *:7002 [cluster]
501 43020 1 0 5:47上午 ?? 0:06.29 /Volumes/work/redis-5.0.8/src/redis-server *:7003 [cluster]
501 43022 1 0 5:47上午 ?? 0:06.29 /Volumes/work/redis-5.0.8/src/redis-server *:7004 [cluster]
501 43024 1 0 5:47上午 ?? 0:06.25 /Volumes/work/redis-5.0.8/src/redis-server *:7005 [cluster]
501 43026 1 0 5:47上午 ?? 0:06.24 /Volumes/work/redis-5.0.8/src/redis-server *:7006 [cluster]
501 43109 1 0 6:12上午 ?? 0:01.31 /Volumes/work/redis-5.0.8/src/redis-server *:7001 [cluster]
501 43141 1 0 6:18上午 ?? 0:00.03 /Volumes/work/redis-5.0.8/src/redis-server *:7007 [cluster]
501 43143 1 0 6:18上午 ?? 0:00.03 /Volumes/work/redis-5.0.8/src/redis-server *:7008 [cluster]
但是我们可以看到虽然进程启动了,但是并未加到集群中去:
127.0.0.1:7002> cluster nodes
8891bfe505da42298be048364ed003b83dc52139 127.0.0.1:7005@17005 master - 0 1586211626238 7 connected 0-5460
9d6d78888e579442b209fca95af13b6ece4810b6 127.0.0.1:7004@17004 slave 6494df31d4ed564d80947c9d39369cc7cfb6c0e6 0 1586211626741 4 connected
981ad9769245c140c0bd9ee239472dc6e2cb07eb 127.0.0.1:7006@17006 slave d7a0d77d2f0fa05ccf4a14e379b52044b212607e 0 1586211626036 6 connected
d7a0d77d2f0fa05ccf4a14e379b52044b212607e 127.0.0.1:7002@17002 myself,master - 0 1586211625000 2 connected 5461-10922
6494df31d4ed564d80947c9d39369cc7cfb6c0e6 127.0.0.1:7003@17003 master - 0 1586211626540 3 connected 10923-16383
4c7fcd06c55ceec27b5bbc450b99159282e7783e 127.0.0.1:7001@17001 slave 8891bfe505da42298be048364ed003b83dc52139 0 1586211627751 7 connected
执行集群节点并没有返现我们的节点数据,这个时候需要把启动的节点数据增加到集群中去,执行命令:./redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7005:
192:src houjing$ ./redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001
>>> Adding node 127.0.0.1:7007 to cluster 127.0.0.1:7001
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: e83dc175f217148444a07ed367fea54ed6b3e2aa 127.0.0.1:7001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 4686809f8673bc918f03fd8642c410c1ca647a39 127.0.0.1:7004
slots: (0 slots) slave
replicates a3b2d4619e3ad17ea86f69a05543b12aa722a864
S: 10eed7c7bbbd7e9e427d0ccf7e2d557607d7467f 127.0.0.1:7005
slots: (0 slots) slave
replicates de6820c4780a070ac658ee4bdf98c44b46038d81
M: de6820c4780a070ac658ee4bdf98c44b46038d81 127.0.0.1:7003
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 9624c69e40a36dd1d67fbd21cae75753735f3f02 127.0.0.1:7006
slots: (0 slots) slave
replicates e83dc175f217148444a07ed367fea54ed6b3e2aa
M: a3b2d4619e3ad17ea86f69a05543b12aa722a864 127.0.0.1:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Send CLUSTER MEET to node 127.0.0.1:7007 to make it join the cluster.
[OK] New node added correctly.
127.0.0.1:7005> cluster nodes
de6820c4780a070ac658ee4bdf98c44b46038d81 127.0.0.1:7003@17003 master - 0 1586212133524 3 connected 10923-16383
e83dc175f217148444a07ed367fea54ed6b3e2aa 127.0.0.1:7001@17001 master - 0 1586212134536 1 connected 0-5460
a3b2d4619e3ad17ea86f69a05543b12aa722a864 127.0.0.1:7002@17002 master - 0 1586212133323 2 connected 5461-10922
4686809f8673bc918f03fd8642c410c1ca647a39 127.0.0.1:7004@17004 slave a3b2d4619e3ad17ea86f69a05543b12aa722a864 0 1586212133000 4 connected
a8236394ddd7f210e4df2036bd73968503283cf8 127.0.0.1:7007@17007 master - 0 1586212134333 0 connected
10eed7c7bbbd7e9e427d0ccf7e2d557607d7467f 127.0.0.1:7005@17005 myself,slave de6820c4780a070ac658ee4bdf98c44b46038d81 0 1586212134000 5 connected
9624c69e40a36dd1d67fbd21cae75753735f3f02 127.0.0.1:7006@17006 slave e83dc175f217148444a07ed367fea54ed6b3e2aa 0 1586212134000 6 connected
可以看到7007成功加入到集群节点,但是并未分配slot槽,接下来使用redis-cli命令为7007分配hash槽,找到集群中的任意一个主节点(7001),对其进行重新分片工作。命令: ./redis-cli --cluster reshard 127.0.0.1:7001
192:src houjing$ ./redis-cli --cluster reshard 127.0.0.1:7001
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: e83dc175f217148444a07ed367fea54ed6b3e2aa 127.0.0.1:7001
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 4686809f8673bc918f03fd8642c410c1ca647a39 127.0.0.1:7004
slots: (0 slots) slave
replicates a3b2d4619e3ad17ea86f69a05543b12aa722a864
S: 10eed7c7bbbd7e9e427d0ccf7e2d557607d7467f 127.0.0.1:7005
slots: (0 slots) slave
replicates de6820c4780a070ac658ee4bdf98c44b46038d81
M: de6820c4780a070ac658ee4bdf98c44b46038d81 127.0.0.1:7003
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 9624c69e40a36dd1d67fbd21cae75753735f3f02 127.0.0.1:7006
slots: (0 slots) slave
replicates e83dc175f217148444a07ed367fea54ed6b3e2aa
M: a8236394ddd7f210e4df2036bd73968503283cf8 127.0.0.1:7007
slots: (0 slots) master
M: a3b2d4619e3ad17ea86f69a05543b12aa722a864 127.0.0.1:7002
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 1000
What is the receiving node ID? a8236394ddd7f210e4df2036bd73968503283cf8
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.
Source node #1: all
以上就是要从其余三个master上划分1000个slot到7007节点,7007节点的ID为a8236394ddd7f210e4df2036bd73968503283cf8。两种reshard方式如下:
备注:all是随机的,比如说我们要分出1000个,则3个主节点分别拿出333个,333个,334个节点分别给7007。
此时查看cluster nodes信息如下:
127.0.0.1:7005> cluster nodes
de6820c4780a070ac658ee4bdf98c44b46038d81 127.0.0.1:7003@17003 master - 0 1586212646000 3 connected 11256-16383
e83dc175f217148444a07ed367fea54ed6b3e2aa 127.0.0.1:7001@17001 master - 0 1586212645158 1 connected 333-5460
a3b2d4619e3ad17ea86f69a05543b12aa722a864 127.0.0.1:7002@17002 master - 0 1586212646000 2 connected 5795-10922
4686809f8673bc918f03fd8642c410c1ca647a39 127.0.0.1:7004@17004 slave a3b2d4619e3ad17ea86f69a05543b12aa722a864 0 1586212646572 4 connected
a8236394ddd7f210e4df2036bd73968503283cf8 127.0.0.1:7007@17007 master - 0 1586212646372 7 connected 0-332 5461-5794 10923-11255
10eed7c7bbbd7e9e427d0ccf7e2d557607d7467f 127.0.0.1:7005@17005 myself,slave de6820c4780a070ac658ee4bdf98c44b46038d81 0 1586212645000 5 connected
9624c69e40a36dd1d67fbd21cae75753735f3f02 127.0.0.1:7006@17006 slave e83dc175f217148444a07ed367fea54ed6b3e2aa 0 1586212645000 6 connected
可以看到7007节点拿到了3段合计1000个slot槽,接下来我们为7007增加从节点7008,依旧是先把7008添加到集群中去:./redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7001:
127.0.0.1:7005> cluster nodes
d9daa198ebe389f7c707e6d41c8052e59f29ce0b 127.0.0.1:7008@17008 master - 0 1586212814000 0 connected
de6820c4780a070ac658ee4bdf98c44b46038d81 127.0.0.1:7003@17003 master - 0 1586212814970 3 connected 11256-16383
e83dc175f217148444a07ed367fea54ed6b3e2aa 127.0.0.1:7001@17001 master - 0 1586212815000 1 connected 333-5460
a3b2d4619e3ad17ea86f69a05543b12aa722a864 127.0.0.1:7002@17002 master - 0 1586212815000 2 connected 5795-10922
4686809f8673bc918f03fd8642c410c1ca647a39 127.0.0.1:7004@17004 slave a3b2d4619e3ad17ea86f69a05543b12aa722a864 0 1586212814565 4 connected
a8236394ddd7f210e4df2036bd73968503283cf8 127.0.0.1:7007@17007 master - 0 1586212815574 7 connected 0-332 5461-5794 10923-11255
10eed7c7bbbd7e9e427d0ccf7e2d557607d7467f 127.0.0.1:7005@17005 myself,slave de6820c4780a070ac658ee4bdf98c44b46038d81 0 1586212815000 5 connected
9624c69e40a36dd1d67fbd21cae75753735f3f02 127.0.0.1:7006@17006 slave e83dc175f217148444a07ed367fea54ed6b3e2aa 0 1586212814565 6 connected
可以看到7008添加到了集群,但是目前还是主节点,并且没有hash槽。接下来需要让其变成从节点。
命令:CLUSTER REPLICATE a8236394ddd7f210e4df2036bd73968503283cf8(这个节点给哪个主节点)
192:src houjing$ ./redis-cli -c -p 7008
127.0.0.1:7008> CLUSTER REPLICATE a8236394ddd7f210e4df2036bd73968503283cf8
OK
127.0.0.1:7008> cluster nodes
4686809f8673bc918f03fd8642c410c1ca647a39 127.0.0.1:7004@17004 slave a3b2d4619e3ad17ea86f69a05543b12aa722a864 0 1586213074000 2 connected
a8236394ddd7f210e4df2036bd73968503283cf8 127.0.0.1:7007@17007 master - 0 1586213073000 7 connected 0-332 5461-5794 10923-11255
9624c69e40a36dd1d67fbd21cae75753735f3f02 127.0.0.1:7006@17006 slave e83dc175f217148444a07ed367fea54ed6b3e2aa 0 1586213073000 1 connected
de6820c4780a070ac658ee4bdf98c44b46038d81 127.0.0.1:7003@17003 master - 0 1586213074818 3 connected 11256-16383
e83dc175f217148444a07ed367fea54ed6b3e2aa 127.0.0.1:7001@17001 master - 0 1586213074000 1 connected 333-5460
d9daa198ebe389f7c707e6d41c8052e59f29ce0b 127.0.0.1:7008@17008 myself,slave a8236394ddd7f210e4df2036bd73968503283cf8 0 1586213073000 0 connected
a3b2d4619e3ad17ea86f69a05543b12aa722a864 127.0.0.1:7002@17002 master - 0 1586213074513 2 connected 5795-10922
10eed7c7bbbd7e9e427d0ccf7e2d557607d7467f 127.0.0.1:7005@17005 slave a8236394ddd7f210e4df2036bd73968503283cf8 0 1586213074513 7 connected
如上所示,查看cluster nodes信息则可直到成功实现Redis集群的水平扩容。
我们现实中存在着水平扩展,那么当服务使用量下降时,也存在着节点下线。比如我们要让刚扩容的7007、7008下线,我们先来删除从节点7008:
命令:./redis-cli --cluster del-node 127.0.0.1:7008 d9daa198ebe389f7c707e6d41c8052e59f29ce0b
192:src houjing$ ./redis-cli --cluster del-node 127.0.0.1:7008 d9daa198ebe389f7c707e6d41c8052e59f29ce0b
>>> Removing node d9daa198ebe389f7c707e6d41c8052e59f29ce0b from cluster 127.0.0.1:7008
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
127.0.0.1:7001> cluster nodes
4686809f8673bc918f03fd8642c410c1ca647a39 127.0.0.1:7004@17004 slave a3b2d4619e3ad17ea86f69a05543b12aa722a864 0 1586213383501 4 connected
e83dc175f217148444a07ed367fea54ed6b3e2aa 127.0.0.1:7001@17001 myself,master - 0 1586213383000 1 connected 333-5460
10eed7c7bbbd7e9e427d0ccf7e2d557607d7467f 127.0.0.1:7005@17005 slave a8236394ddd7f210e4df2036bd73968503283cf8 0 1586213383000 7 connected
de6820c4780a070ac658ee4bdf98c44b46038d81 127.0.0.1:7003@17003 master - 0 1586213383000 3 connected 11256-16383
9624c69e40a36dd1d67fbd21cae75753735f3f02 127.0.0.1:7006@17006 slave e83dc175f217148444a07ed367fea54ed6b3e2aa 0 1586213384308 6 connected
a8236394ddd7f210e4df2036bd73968503283cf8 127.0.0.1:7007@17007 master - 0 1586213383300 7 connected 0-332 5461-5794 10923-11255
a3b2d4619e3ad17ea86f69a05543b12aa722a864 127.0.0.1:7002@17002 master - 0 1586213383000 2 connected 5795-10922
接下来删除主节点7007,命令:./redis-cli --cluster reshard 127.0.0.1:7007
192:src houjing$ ./redis-cli --cluster reshard 127.0.0.1:7007
>>> Performing Cluster Check (using node 127.0.0.1:7007)
M: a8236394ddd7f210e4df2036bd73968503283cf8 127.0.0.1:7007
slots:[172-665],[5461-6128],[10923-11588] (1828 slots) master
1 additional replica(s)
M: a3b2d4619e3ad17ea86f69a05543b12aa722a864 127.0.0.1:7002
slots:[6542-10922] (4381 slots) master
1 additional replica(s)
S: 4686809f8673bc918f03fd8642c410c1ca647a39 127.0.0.1:7004
slots: (0 slots) slave
replicates a3b2d4619e3ad17ea86f69a05543b12aa722a864
M: de6820c4780a070ac658ee4bdf98c44b46038d81 127.0.0.1:7003
slots:[12003-16383] (4381 slots) master
S: 9624c69e40a36dd1d67fbd21cae75753735f3f02 127.0.0.1:7006
slots: (0 slots) slave
replicates e83dc175f217148444a07ed367fea54ed6b3e2aa
M: e83dc175f217148444a07ed367fea54ed6b3e2aa 127.0.0.1:7001
slots:[0-171],[666-5460],[6129-6541],[11589-12002] (5794 slots) master
1 additional replica(s)
S: 10eed7c7bbbd7e9e427d0ccf7e2d557607d7467f 127.0.0.1:7005
slots: (0 slots) slave
replicates a8236394ddd7f210e4df2036bd73968503283cf8
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
How many slots do you want to move (from 1 to 16384)? 1828
What is the receiving node ID? a3b2d4619e3ad17ea86f69a05543b12aa722a864
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.
Source node #1: a8236394ddd7f210e4df2036bd73968503283cf8
Source node #2: done
Ready to move 1828 slots.
可以看到我们把7007节点的1828个slot全部移到了7002上,再次查看cluster nodes信息如下:
127.0.0.1:7001> cluster nodes
4686809f8673bc918f03fd8642c410c1ca647a39 127.0.0.1:7004@17004 slave a3b2d4619e3ad17ea86f69a05543b12aa722a864 0 1586214201506 9 connected
e83dc175f217148444a07ed367fea54ed6b3e2aa 127.0.0.1:7001@17001 myself,master - 0 1586214200000 8 connected 0-171 666-5460 6129-6541 11589-12002
10eed7c7bbbd7e9e427d0ccf7e2d557607d7467f 127.0.0.1:7005@17005 slave a3b2d4619e3ad17ea86f69a05543b12aa722a864 0 1586214201000 9 connected
de6820c4780a070ac658ee4bdf98c44b46038d81 127.0.0.1:7003@17003 master - 0 1586214200000 3 connected 12003-16383
9624c69e40a36dd1d67fbd21cae75753735f3f02 127.0.0.1:7006@17006 slave e83dc175f217148444a07ed367fea54ed6b3e2aa 0 1586214200000 8 connected
a8236394ddd7f210e4df2036bd73968503283cf8 127.0.0.1:7007@17007 master - 0 1586214201707 7 connected
a3b2d4619e3ad17ea86f69a05543b12aa722a864 127.0.0.1:7002@17002 master - 0 1586214201000 9 connected 172-665 5461-6128 6542-11588
7007节点还在,但是分配的slot没有了,接下来关闭7007节点,命令:./redis-cli -p 7001 shutdown
127.0.0.1:7001> cluster nodes
a8236394ddd7f210e4df2036bd73968503283cf8 127.0.0.1:7007@17007 master - 1586214471239 1586214469000 7 disconnected
4686809f8673bc918f03fd8642c410c1ca647a39 127.0.0.1:7004@17004 slave a3b2d4619e3ad17ea86f69a05543b12aa722a864 0 1586214473159 9 connected
e83dc175f217148444a07ed367fea54ed6b3e2aa 127.0.0.1:7001@17001 myself,slave 9624c69e40a36dd1d67fbd21cae75753735f3f02 0 1586214473000 8 connected
de6820c4780a070ac658ee4bdf98c44b46038d81 127.0.0.1:7003@17003 master - 0 1586214473000 3 connected 12003-16383
9624c69e40a36dd1d67fbd21cae75753735f3f02 127.0.0.1:7006@17006 master - 0 1586214472653 10 connected 0-171 666-5460 6129-6541 11589-12002
a3b2d4619e3ad17ea86f69a05543b12aa722a864 127.0.0.1:7002@17002 master - 0 1586214474073 9 connected 172-665 5461-6128 6542-11588
10eed7c7bbbd7e9e427d0ccf7e2d557607d7467f 127.0.0.1:7005@17005 slave 9624c69e40a36dd1d67fbd21cae75753735f3f02 0 1586214474175 10 connected
于是实现了7007、7008节点的下线。
需要修改redis.conf 配置文件
cluster-enable yes # 表示这个Redis 是一个cluster节点
cluster-config-file [filename.conf] # cluster的配置文件
cluster-node-timeout 10000 # 节点服务超时时间,用于判定该节点是否下线或切换为从节点
cluster集群中各个redis依次启动完成后,需要使用
./redis-trib.rb create --replicas 1 ip1:port1 ip2:port2 ip3:port3 ip4:port4 ip5:port5 ip6:port6
create 代表创建集群
--replicas: 指定内部结构 1:代表一个master连接一个slave节点 ip1:port1->ip4:port4 ip2:port2->ip5:port5 ip3:port3->ip6:port6
2: 代表一个master连接两个slave节点 ip1:port1->ip3:port3,ip4:port4 ip2:port2->ip5:port5,ip6:port6
cluster集群搭建好之后,需要注意的是要使用 redis-cli -c 来连接 cluster集群。
Redis-Cluster 支持动态的新增和删除节点
新增
./redis-trib.rb add-node [ip1:port1] [ip2:port],新增成功后我们可以通过 cluster nodes 命令查看集群节点信息,我们可以看到 新增的节点是没有被分配 slot槽的。
手动分配槽节点
cluster setslot 5462 node e4fee6a90d5b071ad514cd30f8d5d9a1c13947b3
cluster setslot [槽] node [目标id]
自动分配槽节点
./redis-trib.rb reshard ip:port
删除
对于已经分配了槽区间的节点,我们是无法直接删除的,需要先将槽区间分配出去,然后再进行删除
将槽区间分配到其他节点
./redis-trib.rb reshard ip:port
删除命令
./redis-trib.rb del-node ip:port 目标id
运维:终于不用再背着数万实例的Redis集群了!_Cluster
Redis学习之4种模式实践及机制解析(单机、主从、哨兵、集群)