Redis必学(三)redis多节点集群

1 概述

  集群,即Redis Cluster,是Redis 3.0开始引入的分布式存储方案。

  集群由多个节点(Node)组成,Redis的数据分布在这些节点中。集群中的节点分为主节点和从节点:只有主节点负责读写请求和集群信息的维护;从节点只进行主节点数据和状态信息的复制。
  集群的作用,可以归纳为两点:

  1. 数据分区:数据分区(或称数据分片)是集群最核心的功能。

  集群将数据分散到多个节点,一方面突破了Redis单机内存大小的限制,存储容量大大增加;另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。

  Redis单机内存大小受限问题,在介绍持久化和主从复制时都有提及;例如,如果单机内存太大,bgsave和bgrewriteaof的fork操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出。

  1. 高可用:集群支持主从复制和主节点的自动故障转移(与哨兵类似);当任一节点发生故障时,集群仍然可以对外提供服务。

2 集群搭建

  虽然Redis cluster是Redis3引入的,但是Redis3的创建集群方式有两种:

  1. 一种是通过cluster node 查看集群信息、通过cluster meet添加集群节点、通过cluster replicate创建节点的主从结构。
  2. 一种需要依赖ruby才能使用,redis-trib.rb。
    虽然是分两种方式,但是如果要增加节点还是需要通过cluster meet。

  因此基于Redis3来创建集群还是限制还是很大,要么较为麻烦,要么依赖ruby。
  本节基于Redis5.0.3实现集群搭建,Redis5脱离了对ruby的依赖,可以直接通过./redis-cli --cluster create来创建集群。

2.1 创建配置

节点1:
cp /home/redis5.0.3/redis.conf /home/redis5.0.3/redis_cluster/redis7000.conf
cp /home/redis5.0.3/redis.conf /home/redis5.0.3/redis_cluster/redis7001.conf
节点2:
cp /home/redis5.0.3/redis.conf /home/redis5.0.3/redis_cluster/redis7000.conf
cp /home/redis5.0.3/redis.conf /home/redis5.0.3/redis_cluster/redis7001.conf
节点3:
cp /home/redis5.0.3/redis.conf /home/redis5.0.3/redis_cluster/redis7000.conf
cp /home/redis5.0.3/redis.conf /home/redis5.0.3/redis_cluster/redis7001.conf

2.2 启动服务

在每个节点执行:
/home/redis/redis-5.0.3/src/redis-server /home/redis5.0.3/redis_cluster/redis7000.conf
/home/redis/redis-5.0.3/src/redis-server /home/redis5.0.3/redis_cluster/redis7001.conf

2.3 创建集群

./redis-cli --cluster create 192.168.2.4:7000 192.168.2.5:7000 192.168.2.6:7000 192.168.2.4:7001 192.168.2.5:7001 192.168.2.6:7001 --cluster-replicas 1
创建成功:
在这里插入图片描述

2.4 哈希槽分配

  一个redis集群,所有的键会被分配在16384个插槽,在刚刚创建的集群信息中:
在这里插入图片描述
通过上述信息可以看到,每个主数据库会负责处理其中的一部分插槽:

192.168.2.4:7000主节点负责处理[0-5460]插槽
192.168.2.5:7000主节点负责处理[5461-10922]插槽
192.168.2.6:7000主节点负责处理[10923-16383]插槽

  虽然通过创建集群初始化,自动分配插槽时是连续分配,但是这并不是一定的,可以通过命令来手动分配插槽,这些插槽可以是非连续的。
  那么redis是如何确定将key分配给哪个插槽呢?首先Redis将每个键名的有效部分使用CRC16算法计算出散列值,然后对16384取余,这样就能获取指定槽位,并通过该槽位确定负责节点。这里需要特别之处有效部分的概念:

1. 如果键名包含大括号({})的内容,则有效部分是则是指这部分内容。
2. 如果不存在大括号内容,则整个键名都为有效部分。

例如:hello.world的有效部分就是“hello.world”;
   {user102:}:last.name的有效部分为“user102”。
这里就有一种场景如果两个键的有效部分相同,则两个键存储在同一个插槽内,如{user102:}:last.name,{user102:}:first.name。则可以通过MGET {user102:}:last.name {user102:}:first.name来同时获取两个键的值。
  除了通过./redis-cli --cluster create命令,让redis自动分配哈希槽以外,还有以下几种分配哈希槽的方式:

2.4.1 cluster meet 创建集群(在集群中添加节点)

  如果是通过cluster meet 方式来创建集群,通过cluster meet将节点添加到集群中,就可以使用cluster addslots slot1 slot2 …[slotn]的方式来分配哈希槽,这里的哈希槽可以指定具体槽位,可以是非连续的。

2.4.2 cluster setlots命令

  通过 cluster setlots 命令可以将指定的插槽号迁移到对应节点,这也能说明,插槽号的分配不一定是连续的。

cluster setlots 插槽号 NODE 新节点的运行id

  这个命令只能在空槽的时候用,因为这样的操作只能转移槽为,槽中的键并不能一起连带转移,因此当客户端查找该槽的键时,将会出现“丢失”的现象。
  因此需要在使用该命令之前,需要先获取该槽中有哪些键,并将键转移到目标节点的其他槽中。并且在转移过程中,还需要处理客户端的请求,当数据转移未完成时,对请求做出正确的响应,这里正确的响应,并不一定老节点或者新节点,因为都有可能。为了解决这个问题,redis提供了处理机制,具体操作如下:
  假设要把0号插槽从A迁移到B,此时redis-cli(老版本为redis-trib.rb)需要依次执行如下步骤:

1. 在B执行cluster setslot 0 importing A;
2. 在A执行cluser setslot 0 migrating B;
3. 执行 cluster getkeysinslot 0 获取哈希槽对应的键列表,也就是该槽上的所有键。
4. 对每个键执行migrate命令,将其从A迁移到B;
    migrate 目标节点地址 目标节点端口 键名 数据库号码 超时时间 [copy] [replace]
    migrate 192.168.1.4 7000 abc 0 15999 replication
5. 执行cluster setlots 0 NODE B 完成迁移。

  以上过程是哈希槽和键迁移的全过程,而redis是如何来处理客户端对迁移数据的请求的呢?
  当A收到客户端请求,如果键存在(未发生迁移),则正常处理,否则返回一个ASK跳转请求,告诉客户端键在B中。
当B收到客户端请求,如果客户端接收过A发送的ASK命令,则直接返回键值内容,否则会返回MOVED跳转请求,让客户端发送到A请求数据。

2.5 集群扩容

  新节点接入集群有两种方式:

  1. 作为从节点
  2. 作为主节点

2.5.1 从节点扩容

  使用cluster replicate命令指定主节点即可:

cluster replicate <nodeid>

  这时,集群的哈希槽分布并不会变化。

2.5.2 主节点扩容

主节点扩容分为两部分:

  1. 将节点添加到集群中
  2. 重新分配集群哈希槽

  执行命令:redis
-cli --cluster add-node 192.168.2.7:7000 192.168.2.4:7000 ,将192.168.2.7:7000节点添加到集群中。其中192.168.2.7:7000为新节点的ip和端口,192.168.2.4:7000为老节点的ip和端口。
[root@localhost 7000]# /usr/local/redis/redis-5.0.3/src/redis
-cli --cluster add-node 192.168.2.7:7000 192.168.2.4:7000

Adding node 192.168.2.7:7000 to cluster 192.168.2.4:7000
Performing Cluster Check (using node 192.168.2.4:7000)
M: 662809cf2d5bb138912dea7fb1e452f6e0f149da 192.168.2.4:7000
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 194a31057d2e098483bcd2ad01e1bba6a1af6a7d 192.168.2.4:7001
slots: (0 slots) slave
replicates 7b5f6aa6dcb4d5aca4a94e57ddeea6971b38bba6
S: b0db47b7bbd3694596f293aa522488882e8fe647 192.168.2.5:7001
slots: (0 slots) slave
replicates 33206e9384297092b5b8a85c944f3564e5d983d7
M: 7b5f6aa6dcb4d5aca4a94e57ddeea6971b38bba6 192.168.2.5:7000
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: 33206e9384297092b5b8a85c944f3564e5d983d7 192.168.2.6:7000
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 60a0f7ced303374d8b36e7aa219cbcd4ff5b0caf 192.168.2.6:7001
slots: (0 slots) slave
replicates 662809cf2d5bb138912dea7fb1e452f6e0f149da
[OK] All nodes agree about slots configuration.
Check for open slots…
Check slots coverage…
[OK] All 16384 slots covered.
Send CLUSTER MEET to node 192.168.2.7:7000 to make it join the cluster.
[OK] New node added correctly.

  在老节点执行命令 cluster info

cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:7
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:2831
cluster_stats_messages_pong_sent:2805
cluster_stats_messages_sent:5636
cluster_stats_messages_ping_received:2799
cluster_stats_messages_pong_received:2831
cluster_stats_messages_meet_received:6
cluster_stats_messages_received:5636
192.168.5.100:8001> cluster nodes
194a31057d2e098483bcd2ad01e1bba6a1af6a7d 192.168.2.4:7001@18006 slave 7b5f6aa6dcb4d5aca4a94e57ddeea6971b38bba6 0 1544883929000 6 connected
b0db47b7bbd3694596f293aa522488882e8fe647 192.168.2.5:7001@18004 slave 33206e9384297092b5b8a85c944f3564e5d983d7 0 1544883930910 4 connected
7b5f6aa6dcb4d5aca4a94e57ddeea6971b38bba6 192.168.2.5:7000@18002 master - 0 1544883929000 2 connected 5461-10922
33206e9384297092b5b8a85c944f3564e5d983d7 192.168.2.6:7000@18003 master - 0 1544883928000 3 connected 10923-16383
662809cf2d5bb138912dea7fb1e452f6e0f149da 192.168.2.4:7000@18001 myself,master - 0 1544883928000 1 connected 0-5460
fea53768189af3e3e4849038af13607f59ec84b0 192.168.2.7:7000@18007 master - 0 1544883927000 0 connected
60a0f7ced303374d8b36e7aa219cbcd4ff5b0caf 192.168.2.6:7001@18005 slave 662809cf2d5bb138912dea7fb1e452f6e0f149da 0 1544883929897 5 connected

分配插槽:
在老节点执行命令:–cluster reshard 192.168.2.7:7000

Performing Cluster Check (using node 192.168.2.4:7000)
M: 662809cf2d5bb138912dea7fb1e452f6e0f149da 192.168.2.4:7000
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: 194a31057d2e098483bcd2ad01e1bba6a1af6a7d 192.168.2.4:7001
slots: (0 slots) slave
replicates 7b5f6aa6dcb4d5aca4a94e57ddeea6971b38bba6
S: b0db47b7bbd3694596f293aa522488882e8fe647 192.168.2.5:7001
slots: (0 slots) slave
replicates 33206e9384297092b5b8a85c944f3564e5d983d7
M: 7b5f6aa6dcb4d5aca4a94e57ddeea6971b38bba6 192.168.2.5:7000
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
M: 33206e9384297092b5b8a85c944f3564e5d983d7 192.168.2.6:7000
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
M: fea53768189af3e3e4849038af13607f59ec84b0 192.168.2.7:7000
slots: (0 slots) master
S: 60a0f7ced303374d8b36e7aa219cbcd4ff5b0caf 192.168.2.6:7001
slots: (0 slots) slave
replicates 662809cf2d5bb138912dea7fb1e452f6e0f149da
[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)?
What is the receiving node ID?

  最后一句会询问要分多少个槽出来(i比如1000)?分给哪个节点(192.168.2.7:7000)

How many slots do you want to move (from 1 to 16384)? 1000
What is the receiving node ID? fea53768189af3e3e4849038af13607f59ec84b0

  这里的分配方式有两种:

  1. 从单个节点拿出1000个哈希槽分配给新节点(done)
  2. 从每个节点随机拿出平均分配的哈希槽分配给新节点(all)

上诉两种方式对应的

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: 662809cf2d5bb138912dea7fb1e452f6e0f149da
Source node #2: done

Ready to move 1000 slots.
Source nodes:
M: 662809cf2d5bb138912dea7fb1e452f6e0f149da 192.168.2.4:7000
slots:[0-5460] (5461 slots) master
1 additional replica(s)
Destination node:
M: fea53768189af3e3e4849038af13607f59ec84b0 192.168.2.7:7000
slots: (0 slots) master
Resharding plan:
Moving slot 0 from 662809cf2d5bb138912dea7fb1e452f6e0f149da
Moving slot 1 from 662809cf2d5bb138912dea7fb1e452f6e0f149da
Moving slot 2 from 662809cf2d5bb138912dea7fb1e452f6e0f149da
Moving slot 3 from 662809cf2d5bb138912dea7fb1e452f6e0f149da
.
.
.
Moving slot 996 from 662809cf2d5bb138912dea7fb1e452f6e0f149da
Moving slot 997 from 662809cf2d5bb138912dea7fb1e452f6e0f149da
Moving slot 998 from 662809cf2d5bb138912dea7fb1e452f6e0f149da
Moving slot 999 from 662809cf2d5bb138912dea7fb1e452f6e0f149da
Do you want to proceed with the proposed reshard plan (yes/no)? yes
.
.
.
Moving slot 995 from 192.168.2.4:7000 to 192.168.2.7:7000 :
Moving slot 996 from 192.168.2.4:7000 to 192.168.2.7:7000 :
Moving slot 997 from 192.168.2.4:7000 to 192.168.2.7:7000 :
Moving slot 998 from 192.168.2.4:7000 to 192.168.2.7:7000 :
Moving slot 999 from 192.168.2.4:7000 to 192.168.2.7:7000 :

  至此我们的扩容已经完成,通过cluster nodes命令查看:

194a31057d2e098483bcd2ad01e1bba6a1af6a7d 192.168.2.4:7001@18006 slave 7b5f6aa6dcb4d5aca4a94e57ddeea6971b38bba6 0 1544883929000 6 connected
b0db47b7bbd3694596f293aa522488882e8fe647 192.168.2.5:7001@18004 slave 33206e9384297092b5b8a85c944f3564e5d983d7 0 1544883930910 4 connected
7b5f6aa6dcb4d5aca4a94e57ddeea6971b38bba6 192.168.2.5:7000@18002 master - 0 1544883929000 2 connected 5461-10922
33206e9384297092b5b8a85c944f3564e5d983d7 192.168.2.6:7000@18003 master - 0 1544883928000 3 connected 10923-16383
662809cf2d5bb138912dea7fb1e452f6e0f149da 192.168.2.4:7000@18001 myself,master - 0 1544883928000 1 connected 1000-5460
fea53768189af3e3e4849038af13607f59ec84b0 192.168.2.7:7000@18007 master - 0 1544883927000 0 connected 0-999
60a0f7ced303374d8b36e7aa219cbcd4ff5b0caf 192.168.2.6:7001@18005 slave 662809cf2d5bb138912dea7fb1e452f6e0f149da 0 1544883929897 5 connected

  同时,我们给新节点配置一个从节点,和老节点的结构保持一致:

./redis-cli --cluster add-node 192.168.2.7:7001 192.168.2.4:7000

  这一步和添加主节点的步骤相同,添加完成后,该节点是作为无哈希槽的主节点,需要通过replicate命令为该节点指定主节点,

CLUSTER REPLICATE fea53768189af3e3e4849038af13607f59ec84b0

  至此,添加从节点就算是成功了,通过命令cluster nodes查看集群信息

194a31057d2e098483bcd2ad01e1bba6a1af6a7d 192.168.2.4:7001@18006 slave 7b5f6aa6dcb4d5aca4a94e57ddeea6971b38bba6 0 1544883929000 6 connected
b0db47b7bbd3694596f293aa522488882e8fe647 192.168.2.5:7001@18004 slave 33206e9384297092b5b8a85c944f3564e5d983d7 0 1544883930910 4 connected
7b5f6aa6dcb4d5aca4a94e57ddeea6971b38bba6 192.168.2.5:7000@18002 master - 0 1544883929000 2 connected 5461-10922
33206e9384297092b5b8a85c944f3564e5d983d7 192.168.2.6:7000@18003 master - 0 1544883928000 3 connected 10923-16383
662809cf2d5bb138912dea7fb1e452f6e0f149da 192.168.2.4:7000@18001 myself,master - 0 1544883928000 1 connected 1000-5460
fea53768189af3e3e4849038af13607f59ec84b0 192.168.2.7:7000@18007 master - 0 1544883927000 0 connected 0-999
71404f4e815c2e315926ac788389120f82029958 192.168.2.7:7001@18008 myself,slave fea53768189af3e3e4849038af13607f59ec84b0 0 1544885693000 0 connected
60a0f7ced303374d8b36e7aa219cbcd4ff5b0caf 192.168.2.6:7001@18005 slave 662809cf2d5bb138912dea7fb1e452f6e0f149da 0 1544883929897 5 connected

2.6 集群减容

集群的减容和扩容的过程相反,如果熟悉了扩容过程,减容就非常好理解。减容同样分两种:

  1. 减容从节点
  2. 减容主节点

2.6.1 从节点减容

减容从节点非常方便,直接通过命令删除节点即可:

./redis-cli --cluster del-node 192.168.2.7:7001 71404f4e815c2e315926ac788389120f82029958

2.6.1 主节点减容

减容主节点的过程相对而言比较复杂,是扩容主节点的逆过程:

  1. 将被减节点的哈希槽分配给其他节点
  2. 删除该节点

直接删除将会丢失数据
重新分配哈希槽:

./redis-cli --cluster reshard 192.168.2.7:7000

How many slots do you want to move (from 1 to 16384)? 1000
What is the receiving node ID? 662809cf2d5bb138912dea7fb1e452f6e0f149da

和扩容过程一样,只不过需要将接受的节点设置为其他主机节点。

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: fea53768189af3e3e4849038af13607f59ec84b0
Source node #2: done
.
.
.
.

哈希槽迁移成功后,则执行del-node命令删除节点:

./redis-cli --cluster del-node 192.168.5.100:8007 fea53768189af3e3e4849038af13607f59ec84b0
  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要手动升级Redis集群节点,需要按照以下步骤进行操作。 首先,要确保所有从节点节点已经完成复制同步,并且数据已经完全一致。可以通过执行`info replication`命令来确认。 接下来,需要将节点设置为可写模式之外的只读模式。可以通过在节点Redis配置文件redis.conf中添加`slave-read-only yes`配置项来实现。 然后,需要停止节点Redis服务。可以使用控制台或命令行执行`redis-cli shutdown`命令来停止Redis服务。 在停止节点之后,需要将节点的数据文件和配置文件备份至安全的位置,以防意外情况发生。 然后,可以下载新版本的Redis软件,并解压至适当的目录。 然后,需要更新Redis集群的配置文件redis.conf。可以根据新版本的配置文件模板进行相应的修改,并确保配置项与原来的节点配置保持一致。 接下来,可以启动新版本的Redis服务。可以使用控制台或命令行执行`redis-server redis.conf`命令来启动Redis服务。 在启动新版本的Redis服务之后,需要重新配置集群。可以执行`redis-cli --cluster reconfigure`命令,并按照提示逐个输入集群节点IP地址和端口信息。 最后,可以通过执行`redis-cli cluster nodes`命令来确认节点的升级是否成功,并确保所有节点都已正常工作。 需要注意的是,在升级节点期间要确保集群仍然能够正常提供服务,可以通过将节点设置为只读模式来防止节点被写入数据。此外,还要确保在升级期间没有发生数据丢失或数据不一致的情况。为了避免这种情况,最好提前进行充分的测试和备份工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值