目录
集群环境
一,集群介绍
1、为什么需要redis集群
2、什么是redis集群
二,数据分片
三, 主从复制模型
四,一致性保证
五,集群搭建
1, 集群结构
2,创建配置文件
(1)创建目录并复制配置文件
(2)在目录/cluster/下分别创建 6 个配置文件:
3,启动所有服务
4, 创建集群
5,测试集群
6,查看节点信息
7, 向集群添加值
8, 向集群查询值
(1)计算键 key 应该被放置在哪个槽上
(2) 返回槽 slot 目前包含的键值对数量。
(3)返回 count 个 slot 槽中的键
六, 故障转移
七,集群扩容
1, 创建配置文件
2, 启动服务
3,添加主节点
4,添加从节点
5,分配插槽
八,集群缩容
1,收回分片
2, 删除从节点
3, 删除主节点
九,集群优缺点
1, 优点:
2,缺点:
集群环境
一,集群介绍
1、为什么需要redis集群
在讲Redis集群架构之前,我们先简单讲下Redis单实例的架构,从最开始的一主N从,到读写分离,再到Sentinel哨兵机制,单实例的Redis缓存足以应对大多数的使用场景,也能实现主从故障迁移。
但是,在某些场景下,单实例存Redis缓存会存在的几个问题:
(1)写并发:Redis单实例读写分离可以解决读操作的负载均衡,但对于写操作,仍然是全部落在了master节点上面,在海量数据高并发场景,一个节点写数据容易出现瓶颈,造成master节点的压力上升。
(2)海量数据的存储压力: 单实例Redis本质上只有一台Master作为存储,如果面对海量数据的存储,一台Redis服务器就应付不过来了,而且数据量太大意味着持久化成本高,严重时可能会阻塞服务器,造成服务请求成功率下降,降低服务的稳定性。
针对以上的问题,Redis集群提供了较为完善的方案,解决了存储能力受到单机限制,写操作无法负载均衡的问题。
2、什么是redis集群
Redis3.0加入了Redis的集群模式,实现了数据的分布式存储,对数据进行分片,将不同的数据存储在不同的master节点上面,从而解决了海量数据的存储问题。
Redis集群采用去中心化的思想,没有中心节点的说法,对于客户端来说,整个集群可以看成一个整体,可以连接任意一个节点进行操作,就像操作单一Redis实例一样,不需要任何代理中间件,当客户端操作的key没有分配到该node上时,Redis会返回转向指令,指向正确的node。
Redis也内置了高可用机制,支持N个master节点,每个master节点都可以挂载多个slave节点,当master节点挂掉时,集群会提升它的某个slave节点作为新的master节点。
Redis 集群通过分区来提供一定程度的可用性,在实际环境中当某个节点宕机或者不可达的情况下继续处理命令。Redis 集群的优势:
- 自动分割数据到不同的节点上。
- 整个集群的部分节点失败或者不可达的情况下能够继续处理命令。
二,数据分片
Redis 集群没有使用一致性hash,而是引入了哈希槽(slots)的概念。
通hash算法:将key使用hash算法计算之后,按照节点数量来取余,即hash(key)%N。优点就是比较简单,但是扩容或者摘除节点时需要重新根据映射关系计算,会导致数据重新迁移。 一致性hash算法:为每一个节点分配一个token,构成一个哈希环;查找时先根据key计算hash值,然后顺时针找到第一个大于等于该哈希值的token节点。优点是在加入和删除节点时只影响相邻的两个节点,缺点是加减节点会造成部分数据无法命中,所以一般用于缓存,而且用于节点量大的情况下,扩容一般增加一倍节点保障数据负载均衡。
Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽(slot = CRC16(key)%16384)。集群的每个节点负责一部分hash槽,比如当前集群有3个节点,那么:
- 节点 A 包含 0 到 5500号哈希槽。
- 节点 B 包含5501 到 11000 号哈希槽。
- 节点 C 包含11001 到 16383号哈希槽。
这种结构很容易添加或者删除节点。比如想新添加个节点D,只需要从节点 A、B、C中得到部分哈希槽并分配到D上即可。 如果想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可。由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。
三, 主从复制模型
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品。
假设具有A、B、C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用。
然而如果在集群创建的时候(或者过一段时间)为每个节点添加一个从节点A1、B1、C1,那么整个集群便有三个master节点和三个slave节点组成,这样在节点B失败后,集群便会选举B1为新的主节点继续服务,整个集群便不会因为槽找不到而不可用了。
不过当B和B1 都失败后,集群是不可用的。
四,一致性保证
Redis 并不能保证数据的强一致性,这意味着在实际集群中在特定的条件下可能会丢失写操作。
第一个原因是因为集群是用了异步复制,写操作过程:
- 客户端向主节点B写入一条命令
- 主节点B向客户端回复命令状态
- 主节点将写操作复制给其他从节点 B1, B2 和 B3
主节点对命令的复制工作发生在返回命令回复之后,因为如果每次处理命令请求都需要等待复制操作完成的话,那么主节点处理命令请求的速度将极大地降低 —— 我们必须在性能和一致性之间做出权衡。注意:Redis 集群可能会在将来提供同步写的方法。
Redis 集群另外一种可能会丢失命令的情况是集群出现了网络分区,并且一个客户端与至少包括一个主节点在内的少数实例被孤立。举个例子:假设集群包含 A 、B 、C 、A1 、B1 、C1 六个节点, 其中 A 、B 、C 为主节点, A1 、B1 、C1 为A,B,C的从节点, 还有一个客户端 Z1。假设集群中发生网络分区,那么集群可能会分为两方,大部分的一方包含节点 A 、C 、A1 、B1 和 C1 ,小部分的一方则包含节点 B 和客户端 Z1。
Z1仍然能够向主节点B中写入,如果网络分区发生时间较短,那么集群将会继续正常运作;如果分区的时间足够让大部分的一方将B1选举为新的master,那么Z1写入B中得数据便丢失了。
注意, 在网络分裂出现期间, 客户端 Z1 可以向主节点 B 发送写命令的最大时间是有限制的,这一时间限制称为节点超时时间(node timeout), 是 Redis 集群的一个重要的配置选项。
五,集群搭建
1, 集群结构
准备3台服务器,每台服务器运行两个redis,一主一从。
主机说明 | 主机IP | 端口 |
Master | 192.168.72.101 | 6379 |
Slaver | 192.168.72.101 | 6380 |
Master | 192.168.72.101 | 6381 |
Slave | 192.168.72.101 | 6382 |
Master | 192.168.72.101 | 6383 |
Slave | 192.168.72.101 | 6384 |
说明:为了演示方便,在一台服务器中配置 3 个主节点,3 个从节点,用于演示节点的增加和删除。
关掉之前配置的一主二从三台服务器
[root@localhost rediscluster]# redis-cli -p 6379 shutdown
[root@localhost rediscluster]# redis-cli -p 6380 shutdown
[root@localhost rediscluster]# redis-cli -p 6381 shutdown
[root@localhost rediscluster]# ss -lutup | grep redis
2,创建配置文件
(1)创建目录并复制配置文件
在根下创建 cluster 目录和日志目录
[root@localhost ~]# mkdir -pv /cluster/log
查看创建结果
[root@localhost ~]# cd /cluster
[root@localhost cluster]# ll
复制redis.conf配置文件
[root@localhost cluster]# cp -a /etc/redis/redis.conf /cluster
[root@localhost cluster]# ll
确保有关redis的进程全部关闭
[root@localhost cluster]# ps -ef | grep redis
(2)在目录/cluster/下分别创建 6 个配置文件:
redis-6379.conf、redis-6380.conf、redis-6381.conf、redis-6382.conf、redis-6383.conf、redis-6384.conf。
创建redis-6379.conf文件
[root@localhost cluster]# vim redis-6379.conf
编辑redis-6379.conf文件
#修改pid文件名
pidfile /var/run/redis_6379.pid
#持久化文件存放目录
dir "/cluster"
#修改持久化文件名
dbfilename "dump_6379.rdb"
#绑定地址
bind 0.0.0.0
#让redis可以后台运行
daemonize yes
#注册的实例ip
replica-announce-ip 192.168.206.128
#保护模式
protected-mode no
#日志
logfile /cluster/log/run-6379.log
#开启集群功能
cluster-enabled yes
#设定节点配置文件名,不需要我们创建,由redis自己维护
cluster-config-file /cluster/nodes-6379.conf
#节点心跳失败的超时时间,超过改时间(毫秒),集群自动进行主从切换
cluster-node-timeout 10000
关闭aof持久化
Appendonly no
注意:
- bind 0.0.0.0 表示所有IP都可以访问,当然也可以配置为:bind 192.168.72.101 127.0.0.1,表示只有这两个IP地址可以访问。
- 如果希望开启 aof 持久化功能,则还需添加如下配置:
# 开启aof持久化
appendonly yes
# 配置aof持久化文件名
appendfilename aof-6380.aof
# 配置同步方式
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewirte-min-size 64mb
把redis-6379.conf文件复制 5 份,分别命名为redis-6380.conf、redis-6381.conf、redis-6382.conf、redis-6383.conf ,redis-6384.conf。
[root@localhost cluster]# cp -a redis-6379.conf redis-6380.conf
[root@localhost cluster]# cp -a redis-6379.conf redis-6381.conf
[root@localhost cluster]# cp -a redis-6379.conf redis-6382.conf
[root@localhost cluster]# cp -a redis-6379.conf redis-6383.conf
[root@localhost cluster]# cp -a redis-6379.conf redis-6384.conf
然后使用 vim 编辑器,打开文件做修改。由于所有配置文件的配置项都是一样的,唯一不同的就是端口号,因此,只需要修改端口号即可。此处以6384为例
其它几个文件做同样的操作。
3,启动所有服务
分别启动这 6 个 Redis 服务器。
[root@localhost cluster]# redis-server redis-6379.conf
[root@localhost cluster]# redis-server redis-6380.conf
[root@localhost cluster]# redis-server redis-6381.conf
[root@localhost cluster]# redis-server redis-6382.conf
[root@localhost cluster]# redis-server redis-6383.conf
[root@localhost cluster]# redis-server redis-6384.conf
查看 Redis 服务进程:
[root@localhost cluster]# ps -ef |grep redis
root 2936 1 0 21:19 ? 00:00:00 redis-server 0.0.0.0:6379 [cluster]
root 2942 1 0 21:19 ? 00:00:00 redis-server 0.0.0.0:6380 [cluster]
root 2948 1 0 21:19 ? 00:00:00 redis-server 0.0.0.0:6381 [cluster]
root 2954 1 0 21:19 ? 00:00:00 redis-server 0.0.0.0:6382 [cluster]
root 2960 1 0 21:19 ? 00:00:00 redis-server 0.0.0.0:6383 [cluster]
root 2966 1 0 21:19 ? 00:00:00 redis-server 0.0.0.0:6384 [cluster]
root 2988 2641 0 21:21 pts/0 00:00:00 grep --color=auto redis
同时,在 /cluster 目录中,也生成了这 6 个服务器的节点配置文件名:
[root@localhost cluster]# ll
4, 创建集群
启动好全部 Redis 服务器后,接下来就是如何把这 6 个服务器按预先规划的结构来组合成集群了。在做接下来的操作之前,一定要先确保所有 Redis 实例都已经成功启动,并且对应实例的节点配置文件都已经成功生成。
创建集群需要执行命令来创建集群,在 Redis 6 版本中集群管理已经集成到了redis-cli中,格式如下:
redis-cli --clustercreate --cluster-replicas副本数 主机IP:端口号 主机IP:端口号
注意:如果是源码安装的话这个命令需要在 Redis 安装解压编译后的 src 目录下执行才可以,因为执行这个命令时,会去找 redis-trib.rb 文件。
根据上面的命令格式来创建集群:
[root@localhost cluster]# redis-cli --cluster create --cluster-replicas 1 192.168.206.128:6379 192.168.206.128:6380 192.168.206.128:6381 192.168.206.128:6382 192.168.206.128:6383 192.168.206.128:6384
参数说明:
-`redis-cli --cluster`:代表集群操作命令
-`create`:代表是创建集群
-`--replicas 1`或者`--cluster-replicas 1`:指定集群中每个主节点需要1个从节点,此时`节点总数 ÷ (replicas + 1)`得到的就是master的数量。因此节点列表中的前n个就是master,其它节点都是slave节点,随机分配到不同master。
此处输入yes开始创建集群
Can I set the above configuration? (type 'yes' to accept): yes
然后就可以通过命令查看集群状态:
[root@localhost cluster]# redis-cli -p 6379 cluster nodes
ec2299148222a1d76e2c085b930717a99e00f903 192.168.206.128:6380@16380 master - 0 1677161818000 2 connected 5461-10922
3d4638319b4f046c652545efa2fb3c8659ff92c9 192.168.206.128:6384@16384 slave 3166188c73d2015dfda2a7d4ea843127e0f9ee21 0 1677161819000 1 connected
3166188c73d2015dfda2a7d4ea843127e0f9ee21 192.168.206.128:6379@16379 myself,master - 0 1677161817000 1 connected 0-5460
769275bd1a15f795c38542600fe4b2681daa7511 192.168.206.128:6381@16381 master - 0 1677161820651 3 connected 10923-16383
4e2f2721265873c854e893f4ad74f86b8c62c2cc 192.168.206.128:6382@16382 slave ec2299148222a1d76e2c085b930717a99e00f903 0 1677161819564 2 connected
b30b317892f18d3d77d4f8f7f197f34bdaf74386 192.168.206.128:6383@16383 slave 769275bd1a15f795c38542600fe4b2681daa7511 0 1677161819016 3 connected
5,测试集群
尝试连接 6379 节点(连接任何一个节点都可以),存储一个数据:
连接6379
[root@localhost cluster]# redis-cli -p 6379
存储数据
127.0.0.1:6379> set num 123
读取数据
127.0.0.1:6379> get num
再次存储,结果出错,插槽为15495,超过5460
127.0.0.1:6379> set a 1
(error) MOVED 15495 192.168.206.128:6381
连接集群注意添加-c选项
[root@localhost cluster]# redis-cli -p 6379 -c
存储数据
127.0.0.1:6379> set a 1
读取数据
192.168.206.128:6381> get a
"1"
6379连接集群,存储a 时,会自动从6379跳转到6381
说明:
- -h:如果在配置文件中绑定了127.0.0.1就可以不用输入-h参数,否则需要输入
- -p:参数是指定端口,如果不输入则表示端口为默认端口6379,如果不是默认端口则必须提供-p参数
- -c:参数表示连接到集群
6,查看节点信息
如果要查看集群中节点信息,可以通过 cluster nodes 命令:
[root@localhost cluster]# redis-cli -p 6379 cluster nodes
ec2299148222a1d76e2c085b930717a99e00f903 192.168.206.128:6380@16380 master - 0 1677161818000 2 connected 5461-10922
3d4638319b4f046c652545efa2fb3c8659ff92c9 192.168.206.128:6384@16384 slave 3166188c73d2015dfda2a7d4ea843127e0f9ee21 0 1677161819000 1 connected
3166188c73d2015dfda2a7d4ea843127e0f9ee21 192.168.206.128:6379@16379 myself,master - 0 1677161817000 1 connected 0-5460
769275bd1a15f795c38542600fe4b2681daa7511 192.168.206.128:6381@16381 master - 0 1677161820651 3 connected 10923-16383
4e2f2721265873c854e893f4ad74f86b8c62c2cc 192.168.206.128:6382@16382 slave ec2299148222a1d76e2c085b930717a99e00f903 0 1677161819564 2 connected
b30b317892f18d3d77d4f8f7f197f34bdaf74386 192.168.206.128:6383@16383 slave 769275bd1a15f795c38542600fe4b2681daa7511 0 1677161819016 3 connected
7, 向集群添加值
在集群环境下,由于 redis-cli 每次录入、查询键值时,Redis 都会计算出该 key 对应的插槽值,并交给对应插槽所在的节点进行处理。如果不是该客户端对应服务器的插槽 Redis 会报错,并告知应前往的 Redis 实例地址和端口。
在集群下使用 mset 或 mget 来添加多个值或查询多个值时会报错
192.168.206.128:6380> mset name lisi age 20
(error) CROSSSLOT Keys in request don't hash to the same slot
192.168.206.128:6380>
如何解决这种批量添加的操作
我们可以使用自定义组来完成,通过一对大括号{}来定义一个相同的组名,从而使 key 中的 {} 内相同内容的键值对放到同一个 slot 中。因此上面示例修改为如下方式:
192.168.206.128:6380> mset name{user} lisi age{user} 20
OK
192.168.206.128:6380> get name{user}
"lisi"
192.168.206.128:6380> get age{user}
"20"
注意:
- 大括号需要加到每个 key 的后面,不能有空格
- 自定义组的名称可以任意
添加一个值
192.168.206.128:6381> set test 123
-> Redirected to slot [6918] located at 192.168.206.128:6380
OK
192.168.206.128:6380> get test
"123"
添加多个值
192.168.206.128:6380> mset name{user} lisi age{user} 20
OK
192.168.206.128:6380> get name{user}
"lisi"
192.168.206.128:6380> get age{user}
"20"
8, 向集群查询值
向集群查询值的命令格式为:
CLUSTER GETKEYSINSLOT <slot> <count>
它会返回 count 个 slot 槽中的键。
(1)计算键 key 应该被放置在哪个槽上
CLUSTER KEYSLOT <key>
查看a在哪个插槽上
192.168.206.128:6380> cluster keyslot a
(integer) 15495
192.168.206.128:6380>
(2) 返回槽 slot 目前包含的键值对数量。
CLUSTER COUNTKEYSINSLOT <slot>
只能统计自己插槽所在范围的值
查看卡槽5474中有几个值
192.168.206.128:6380> cluster countkeysinslot 5474
(integer) 2
(3)返回 count 个 slot 槽中的键
CLUSTER GETKEYSINSLOT <slot> <count>
统计卡槽5474中的10个值
192.168.206.128:6380> cluster getkeysinslot 5474 10
1) "age{user}"
2) "name{user}"
192.168.206.128:6380>
六, 故障转移
下面来演示当某个主节点宕机后,从节点是否能自动切换为主节点。
6379的从是6384
假设我们让 6379 服务器宕机:
192.168.206.128:6379> shutdown
not connected> exit
[root@localhost cluster]# ps -ef | grep redis
连接6379的从节点6384并查看集群状态
可以发现,6379 所在的从机 6384 已经自动切换为了 master。
[root@localhost cluster]# redis-cli -p 6384
127.0.0.1:6384> cluster nodes
ec2299148222a1d76e2c085b930717a99e00f903 192.168.206.128:6380@16380 master - 0 1677165739000 2 connected 5461-10922
3d4638319b4f046c652545efa2fb3c8659ff92c9 192.168.206.128:6384@16384 myself,master - 0 1677165739000 7 connected 0-5460
769275bd1a15f795c38542600fe4b2681daa7511 192.168.206.128:6381@16381 master - 0 1677165740000 3 connected 10923-16383
3166188c73d2015dfda2a7d4ea843127e0f9ee21 192.168.206.128:6379@16379 master,fail - 1677165593024 1677165588000 1 disconnected
4e2f2721265873c854e893f4ad74f86b8c62c2cc 192.168.206.128:6382@16382 slave ec2299148222a1d76e2c085b930717a99e00f903 0 1677165738375 2 connected
b30b317892f18d3d77d4f8f7f197f34bdaf74386 192.168.206.128:6383@16383 slave 769275bd1a15f795c38542600fe4b2681daa7511 0 1677165740386 3 connected
重新启动6379这台服务器并查看集群状态,6379变为6384的从
可以发现,6379 成了 6384 的从服务器了,故障成功转移。
[root@localhost cluster]# redis-server redis-6379.conf
[root@localhost cluster]# redis-cli -p 6380 cluster nodes
3d4638319b4f046c652545efa2fb3c8659ff92c9 192.168.206.128:6384@16384 master - 0 1677166057000 7 connected 0-5460
ec2299148222a1d76e2c085b930717a99e00f903 192.168.206.128:6380@16380 myself,master - 0 1677166056000 2 connected 5461-10922
3166188c73d2015dfda2a7d4ea843127e0f9ee21 192.168.206.128:6379@16379 slave 3d4638319b4f046c652545efa2fb3c8659ff92c9 0 1677166056000 7 connected
4e2f2721265873c854e893f4ad74f86b8c62c2cc 192.168.206.128:6382@16382 slave ec2299148222a1d76e2c085b930717a99e00f903 0 1677166059800 2 connected
769275bd1a15f795c38542600fe4b2681daa7511 192.168.206.128:6381@16381 master - 0 1677166058794 3 connected 10923-16383
b30b317892f18d3d77d4f8f7f197f34bdaf74386 192.168.206.128:6383@16383 slave 769275bd1a15f795c38542600fe4b2681daa7511 0 1677166059000 3 connected
问:如果所有某段插槽的主从节点都宕机了,Redis 服务是否还能继续?
答:当发生某段插槽的主从都宕机后,如果在 redis.conf 配置文件中的 cluster-require-full-coverage 参数的值为 yes ,那么整个集群都挂掉;如果参数的值为 no ,那么该段插槽数据全都不能使用,也无法存储。
七,集群扩容
我们向现有集群中添加两个节点,这两个节点做了一主一从。主节点的端口号为 6385,从节点的端口号为 6386。
1, 创建配置文件
按照 11.5.3 节分别创建好 redis-6385.conf 和 redis-6386.conf 配置文件。
[root@localhost cluster]# cp redis-6379.conf redis-6385.conf
[root@localhost cluster]# cp redis-6379.conf redis-6386.conf
修改redis-6385.conf ,redis-6386.conf 中的端口号,下面以redis-6385.conf 为例
#把文件/cluster/redis.conf读取到此文件中
include /cluster/redis.conf
#端口号为6385
port 6385
#修改pid文件名
pidfile /var/run/redis_6385.pid
#持久化文件存放目录
dir "/cluster"
#修改持久化文件名
dbfilename "dump_6385.rdb"
#绑定地址
bind 0.0.0.0
#让redis可以后台运行
daemonize yes
#注册的实例ip
replica-announce-ip 192.168.206.128
#保护模式
protected-mode no
#日志
logfile /cluster/log/run-6385.log
#开启集群功能
cluster-enabled yes
#设定节点配置文件名,不需要我们创建,由redis自己维护
cluster-config-file /cluster/nodes-6385.conf
#节点心跳失败的超时时间,超过改时间(毫秒),集群自动进行主从切换
cluster-node-timeout 10000
2, 启动服务
然后使用如下命令来启动这两台 Redis 服务器。
启动后可查看进程进行确认。
[root@localhost cluster]# redis-server redis-6385.conf
[root@localhost cluster]# redis-server redis-6386.conf
[root@localhost cluster]# ps -ef | grep redis
3,添加主节点
添加节点到集群的语法格式为:
redis-cli --clusteradd-node new_host:new_port existing_host:existing_port
--cluster-slave
--cluster-master-id<arg>
add-node命令用于添加节点到集群中,参数说明如下:
- new_host:被添加节点的主机地址
- new_port:被添加节点的端口号
- existing_host:目前集群中已经存在的任一主机地址
- existing_port:目前集群中已经存在的任一端口地址
- --cluster-slave:用于添加从(Slave)节点
- --cluster-master-id:指定主(Master)节点的ID(唯一标识)字符串
把6385添加到6382集群中,6385变为主且没有从
[root@localhost cluster]# redis-cli --cluster add-node 192.168.206.128:6385 192.168.206.128:6382
[root@localhost cluster]# redis-cli cluster nodes
4,添加从节点
首先需要 查看 6385 节点的 ID 值:
[root@localhost cluster]# redis-cli cluster nodes
ec2299148222a1d76e2c085b930717a99e00f903 192.168.206.128:6380@16380 master - 0 1677167002159 2 connected 5461-10922
3166188c73d2015dfda2a7d4ea843127e0f9ee21 192.168.206.128:6379@16379 myself,slave 3d4638319b4f046c652545efa2fb3c8659ff92c9 0 1677167002000 7 connected
3d4638319b4f046c652545efa2fb3c8659ff92c9 192.168.206.128:6384@16384 master - 0 1677167002000 7 connected 0-5460
769275bd1a15f795c38542600fe4b2681daa7511 192.168.206.128:6381@16381 master - 0 1677167003164 3 connected 10923-16383
4e2f2721265873c854e893f4ad74f86b8c62c2cc 192.168.206.128:6382@16382 slave ec2299148222a1d76e2c085b930717a99e00f903 0 1677167001000 2 connected
078269f8a81bd8c99cdaba1535bbc97b4aa9d207 192.168.206.128:6385@16385 master - 0 1677166999000 0 connected
b30b317892f18d3d77d4f8f7f197f34bdaf74386 192.168.206.128:6383@16383 slave 769275bd1a15f795c38542600fe4b2681daa7511 0 1677167001000 3 connected
可以得到,ID值为:078269f8a81bd8c99cdaba1535bbc97b4aa9d207 ,再用如下命令来添加从节点:
[root@localhost cluster]# redis-cli --cluster add-node 192.168.206.128:6386 192.168.206.128:6379 --cluster-slave --cluster-master-id 078269f8a81bd8c99cdaba1535bbc97b4aa9d207
查看集群状态:
[root@localhost cluster]# redis-cli -p 6379 -c
127.0.0.1:6379> cluster nodes
b1683231ab0c921004fa04fce41d7595070166cf 192.168.206.128:6386@16386 slave 078269f8a81bd8c99cdaba1535bbc97b4aa9d207 0 1677167458372 0 connected
ec2299148222a1d76e2c085b930717a99e00f903 192.168.206.128:6380@16380 master - 0 1677167456060 2 connected 5461-10922
3166188c73d2015dfda2a7d4ea843127e0f9ee21 192.168.206.128:6379@16379 myself,slave 3d4638319b4f046c652545efa2fb3c8659ff92c9 0 1677167458000 7 connected
3d4638319b4f046c652545efa2fb3c8659ff92c9 192.168.206.128:6384@16384 master - 0 1677167459377 7 connected 0-5460
769275bd1a15f795c38542600fe4b2681daa7511 192.168.206.128:6381@16381 master - 0 1677167457000 3 connected 10923-16383
4e2f2721265873c854e893f4ad74f86b8c62c2cc 192.168.206.128:6382@16382 slave ec2299148222a1d76e2c085b930717a99e00f903 0 1677167455358 2 connected
078269f8a81bd8c99cdaba1535bbc97b4aa9d207 192.168.206.128:6385@16385 master - 0 1677167457000 0 connected
b30b317892f18d3d77d4f8f7f197f34bdaf74386 192.168.206.128:6383@16383 slave 769275bd1a15f795c38542600fe4b2681daa7511 0 1677167457367 3 connected
5,分配插槽
由于集群中增加了新节点,需要对现有数据重新进行分片操作。重新分片的语法如下:
redis-cli --clusterreshard host:port
--cluster-from<arg>
--cluster-to<arg>
--cluster-slots<arg>
--cluster-yes
--cluster-timeout<arg>
--cluster-pipeline<arg>
--cluster-replace
reshard命令用于重新分片,参数说明如下:
- host:集群中已经存在的任意主机地址
- port:集群中已经存在的任意主机对应的端口号
- --cluster-from:表示slot目前所在的节点node ID,多个ID用逗号分隔
- --cluster-to:表示需要分配节点的node ID
- --cluster-slot:分配的slot数量
- --cluster-yes:指定迁移时的确认输入
- --cluster-timeout:设置migrate命令的超时时间
- --cluster-pipeline:定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10
- --cluster-replace:是否直接replace到目标节点
节点添加成功,但是发现没有分配插槽,所以还没有使用此节点。接下来从6380为6385分100个配槽:
[root@localhost cluster]# redis-cli --cluster reshard 192.168.206.128:6380 --cluster-from ec2299148222a1d76e2c085b930717a99e00f903 --cluster-to 078269f8a81bd8c99cdaba1535bbc97b4aa9d207 --cluster-slots 100 --cluster-yes --cluster-timeout 5000 --cluster-pipeline 10 --cluster-replace
执行上面的命令后,就会从指定的6380节点上分配100个槽给6385节点。查看节点信息可以发现已经分配成功:
[root@localhost cluster]# redis-cli cluster nodes
3166188c73d2015dfda2a7d4ea843127e0f9ee21 192.168.206.128:6379@16379 myself,slave 3d4638319b4f046c652545efa2fb3c8659ff92c9 0 1677200606000 7 connected
4e2f2721265873c854e893f4ad74f86b8c62c2cc 192.168.206.128:6382@16382 slave ec2299148222a1d76e2c085b930717a99e00f903 0 1677200605000 2 connected
3d4638319b4f046c652545efa2fb3c8659ff92c9 192.168.206.128:6384@16384 master - 0 1677200604004 7 connected 0-5460
078269f8a81bd8c99cdaba1535bbc97b4aa9d207 192.168.206.128:6385@16385 master - 0 1677200604000 8 connected 5461-5660
b1683231ab0c921004fa04fce41d7595070166cf 192.168.206.128:6386@16386 slave 078269f8a81bd8c99cdaba1535bbc97b4aa9d207 0 1677200603000 8 connected
b30b317892f18d3d77d4f8f7f197f34bdaf74386 192.168.206.128:6383@16383 slave 769275bd1a15f795c38542600fe4b2681daa7511 0 1677200606216 3 connected
769275bd1a15f795c38542600fe4b2681daa7511 192.168.206.128:6381@16381 master - 0 1677200603000 3 connected 10923-16383
ec2299148222a1d76e2c085b930717a99e00f903 192.168.206.128:6380@16380 master - 0 1677200605210 2 connected 5661-10922
八,集群缩容
在从集群中删除节点时要根据以下步骤来执行:
- 首先需要把要删除节点的slot收加
- 然后先删除从节点,如果先删除主节点,那么从节点会进行故障转移
- 最后再删除主节点
1,收回分片
执行如下命令把6385节点的所有槽分配给6384节点:
[root@localhost cluster]# redis-cli --cluster reshard 192.168.206.128:6385 --cluster-from 078269f8a81bd8c99cdaba1535bbc97b4aa9d207 --cluster-to 3d4638319b4f046c652545efa2fb3c8659ff92c9 --cluster-slots 200 --cluster-yes --cluster-timeout 5000 --cluster-pipeline 10 --cluster-replace
查看集群状态:
[root@localhost cluster]# redis-cli cluster nodes
3166188c73d2015dfda2a7d4ea843127e0f9ee21 192.168.206.128:6379@16379 myself,slave 3d4638319b4f046c652545efa2fb3c8659ff92c9 0 1677201106000 9 connected
4e2f2721265873c854e893f4ad74f86b8c62c2cc 192.168.206.128:6382@16382 slave ec2299148222a1d76e2c085b930717a99e00f903 0 1677201109706 2 connected
3d4638319b4f046c652545efa2fb3c8659ff92c9 192.168.206.128:6384@16384 master - 0 1677201109000 9 connected 0-5660
078269f8a81bd8c99cdaba1535bbc97b4aa9d207 192.168.206.128:6385@16385 master - 0 1677201109000 8 connected
b1683231ab0c921004fa04fce41d7595070166cf 192.168.206.128:6386@16386 slave 3d4638319b4f046c652545efa2fb3c8659ff92c9 0 1677201110711 9 connected
b30b317892f18d3d77d4f8f7f197f34bdaf74386 192.168.206.128:6383@16383 slave 769275bd1a15f795c38542600fe4b2681daa7511 0 1677201108000 3 connected
769275bd1a15f795c38542600fe4b2681daa7511 192.168.206.128:6381@16381 master - 0 1677201109000 3 connected 10923-16383
ec2299148222a1d76e2c085b930717a99e00f903 192.168.206.128:6380@16380 master - 0 1677201110008 2 connected 5661-10922
可以发现 6385 的 slot 已经收回。6383 由5460变为5660
2, 删除从节点
删除节点的语法格式为:
redis-cli --clusterdel-node host:port node_id
del-node命令用于从集群中删除节点,参数说明如下:
- host:集群中已经存在的主机地址
- port:集群中已经存在的主机对应的端口号
- node_id:要删除的节点ID
执行下面的语句删除6386从节点:
[root@localhost cluster]# redis-cli --cluster del-node 192.168.206.128:6379 b1683231ab0c921004fa04fce41d7595070166cf
从节点 3686 已经成功从集群中删除。
[root@localhost cluster]# redis-cli cluster nodes
3166188c73d2015dfda2a7d4ea843127e0f9ee21 192.168.206.128:6379@16379 myself,slave 3d4638319b4f046c652545efa2fb3c8659ff92c9 0 1677201666000 9 connected
4e2f2721265873c854e893f4ad74f86b8c62c2cc 192.168.206.128:6382@16382 slave ec2299148222a1d76e2c085b930717a99e00f903 0 1677201666000 2 connected
3d4638319b4f046c652545efa2fb3c8659ff92c9 192.168.206.128:6384@16384 master - 0 1677201667000 9 connected 0-5660
078269f8a81bd8c99cdaba1535bbc97b4aa9d207 192.168.206.128:6385@16385 master - 0 1677201667425 8 connected
b30b317892f18d3d77d4f8f7f197f34bdaf74386 192.168.206.128:6383@16383 slave 769275bd1a15f795c38542600fe4b2681daa7511 0 1677201664410 3 connected
769275bd1a15f795c38542600fe4b2681daa7511 192.168.206.128:6381@16381 master - 0 1677201666000 3 connected 10923-16383
ec2299148222a1d76e2c085b930717a99e00f903 192.168.206.128:6380@16380 master - 0 1677201668430 2 connected 5661-10922
3, 删除主节点
执行如下命令来删除 3685 主节点:
[root@localhost cluster]# redis-cli --cluster del-node 192.168.206.128:6379 078269f8a81bd8c99cdaba1535bbc97b4aa9d207
主节点 3685 已经成功从集群中删除。
[root@localhost cluster]# redis-cli cluster nodes
3166188c73d2015dfda2a7d4ea843127e0f9ee21 192.168.206.128:6379@16379 myself,slave 3d4638319b4f046c652545efa2fb3c8659ff92c9 0 1677201786000 9 connected
4e2f2721265873c854e893f4ad74f86b8c62c2cc 192.168.206.128:6382@16382 slave ec2299148222a1d76e2c085b930717a99e00f903 0 1677201787002 2 connected
3d4638319b4f046c652545efa2fb3c8659ff92c9 192.168.206.128:6384@16384 master - 0 1677201785000 9 connected 0-5660
b30b317892f18d3d77d4f8f7f197f34bdaf74386 192.168.206.128:6383@16383 slave 769275bd1a15f795c38542600fe4b2681daa7511 0 1677201788007 3 connected
769275bd1a15f795c38542600fe4b2681daa7511 192.168.206.128:6381@16381 master - 0 1677201788000 3 connected 10923-16383
ec2299148222a1d76e2c085b930717a99e00f903 192.168.206.128:6380@16380 master - 0 1677201789012 2 connected 5661-10922
九,集群优缺点
1, 优点:
- 扩容方便
- 分摊压力
- 无中心配置相对简单
2,缺点:
- 多键操作是不被支持的
- 多键的Redis事务是不被支持的。lua脚本不被支持