• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Redis集群(Cluster)

武飞扬头像
WorkLee
帮助2

学新通

Redis集群(Cluster)

单台redis容量限制,如何进行扩容?继续加内存、加硬件么?单台redis并发写量太大有性能瓶颈,如何解决?redis3.0中提供了集群可以解决这些问题。

redis集群是对redis的水平扩容,即启动N个redis节点,将整个数据分布存储在这个N个节点中,每个节点存储总数据的1/N。

如下图:由3台master和3台slave组成的redis集群,每台master承接客户端三分之一请求和写入的数据,当master挂掉后,slave会自动替代master,做到高可用。

学新通

集群如何配置,示例演示

需求:配置3主3从集群

配置一个3主3从的集群,每个主下面挂一个slave,master挂掉后,slave会被提升为master。

为了方便,我们在一台机器上进行模拟,我的机器ip是:192.168.1.100,通过端口来区分6个不同的节点,配置信息如下:

学新通

创建案例工作目录:cluster
#创建/opt/cluster目录,本次所有操作,均在cluster目录进行。
# 方便演示,停止所有的redis
kill -9 redis的id
mkdir /opt/cluster
cd /opt/cluster/
将redis.conf复制到cluster目录
#我测试的Linux环境,redis.conf在/usr/local/redis/redis-6.2.1/中
cp /usr/local/redis/redis-6.2.1/redis.conf /opt/cluster/
创建master1的配置文件:redis-6379.conf
#在/opt/cluster目录创建redis-6379.conf文件,内容如下
#注意192.168.1.100是我测试机器的ip,大家需要替换为自己的
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.1.100
dir /opt/cluster/
port 6379
dbfilename dump_6379.rdb
pidfile /var/run/redis_6379.pid
logfile "./6379.log"
cluster-enabled yes
cluster-config-file node-6379.conf
cluster-node-timeout 15000
创建master2的配置文件:redis-6380.conf
#在/opt/cluster目录创建redis-6380.conf文件,和上面master的类似,只是将6379换成6380了
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.1.100
dir /opt/cluster/
port 6380
dbfilename dump_6380.rdb
pidfile /var/run/redis_6380.pid
logfile "./6380.log"
cluster-enabled yes
cluster-config-file node-6380.conf
cluster-node-timeout 15000
创建master3的配置文件:redis-6381.conf
#在/opt/cluster目录创建redis-6381.conf文件
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.1.100
dir /opt/cluster/
port 6381
dbfilename dump_6381.rdb
pidfile /var/run/redis_6381.pid
logfile "./6381.log"
cluster-enabled yes
cluster-config-file node-6381.conf
cluster-node-timeout 15000
创建slave1的配置文件:redis-6389.conf
#在/opt/cluster目录创建redis-6389.conf文件,内容如下
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.1.100
dir /opt/cluster/
port 6389
dbfilename dump_6389.rdb
pidfile /var/run/redis_6389.pid
logfile "./6389.log"
cluster-enabled yes
cluster-config-file node-6389.conf
cluster-node-timeout 15000
创建slave2的配置文件:redis-6390.conf
#在/opt/cluster目录创建redis-6390.conf文件,内容如下
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.1.100
dir /opt/cluster/
port 6390
dbfilename dump_6390.rdb
pidfile /var/run/redis_6390.pid
logfile "./6390.log"
cluster-enabled yes
cluster-config-file node-6390.conf
cluster-node-timeout 15000
创建slave3的配置文件:redis-6391.conf
#在/opt/cluster目录创建redis-6391.conf文件,内容如下
include /opt/cluster/redis.conf
daemonize yes
bind 192.168.1.100
dir /opt/cluster/
port 6391
dbfilename dump_6391.rdb
pidfile /var/run/redis_6391.pid
logfile "./6391.log"
cluster-enabled yes
cluster-config-file node-6391.conf
cluster-node-timeout 15000
启动master、slave1、slave2
redis-server /opt/cluster/redis-6379.conf
redis-server /opt/cluster/redis-6380.conf
redis-server /opt/cluster/redis-6381.conf
redis-server /opt/cluster/redis-6389.conf
redis-server /opt/cluster/redis-6390.conf
redis-server /opt/cluster/redis-6391.conf
#可以通过    ps -ef | grep redis    查看启动情况
#ps -ef | grep redis信息省略
确保node-xxxx.conf文件已正常生成

稍后我们会将6个实例合并到一个集群,在组合之前,我们要确保6个redis实例启动后,nodes-xxxx.conf文件都生成正常,如下:

cd /opt/cluster/
ll
#可以通过上述命令,查看到/opt/cluster/目录下
#如果启动一切正常,会出现6个nodes-xxxx.conf文件
#nodes-xxxx.conf分别对应端口6379、6380、6381、6389、6390、6391的文件
#当然还可以看到相应的log文件和redis-xxxx.conf文件
将6个节点合成一个集群
#执行下面命令,将6个redis合体
#我测试的Linux环境,redis目录是/usr/local/redis/redis-6.2.1/
/usr/local/redis/redis-6.2.1/redis-6.2.1/src/redis-cli --cluster create --cluster-replicas 1 192.168.1.100:6379 192.168.1.100:6380 192.168.1.100:6381 192.168.1.100:6389 192.168.1.100:6390 192.168.1.100:6391
  • 合体的命令后面会跟上所有节点的ip:port列表,多个之间用空格隔开,注意ip不要写127.0.0.1,要写真实ip
  • --cluster-replicas 1:表示采用最简单的方式配置集群,即每个master配1个slave,6个节点就形成了3主3从

执行过程如下,期间会让我们确定是否同样这样的分配方式,输入:yes,然后等几秒,集群合体成功

#执行完合成集群命令省略
#中间会有确认环境
Can I set the above configuration? (type 'yes' to accept): 
#输入yes将继续执行
#等待执行完毕
连接集群节点,查看集群信息:cluster nodes
#需要使用redis-cli -c命令连接集群中6个节点中任何一个节点都可以
#注意和之前的连接参数有点不同redis-cli命令后面多了一个-c参数,表示采用集群的方式连接
#连上以后,然后使用cluster nodes可以查看集群节点信息,如下
192.168.1.100:6379> cluster nodes
#信息展示省略,执行完cluster nodes,按照之前的配置会出现6条信息

截图解释一下,如下:

学新通

集群中的每个节点都会生成一个ID,这个ID信息会被写到node-xxxx.conf文件中。因为节点的ip和端口可能会发生变化,但是节点的ID是不会变的,其他节点可以通过其他节点的ID来认识各个节点。

验证集群数据的读写操作
#连接6379这个节点,然后执行一个set操作(注意这里我用的是redis-cli -c命令)
redis-cli -c -h 192.168.1.100 -p 6379
192.168.1.100:6379> set name zhangsan
-> Redirected to slot [5798] located at 192.168.1.100:6380
OK
#在6379上操作的,但是请求被转发到了6380这个节点去处理了
#这里就是我们后面要说的slot的知识了,后面会提及
redis集群如何分配这6个节点

一个集群至少有3个主节点,因为新master的选举需要大于半数的集群master节点同意才能选举成功,如果只有两个master节点,当其中一个挂了,是达不到选举新master的条件的。

选项--cluster-replicas 1表示我们希望为集群中的每个主节点创建一个从节点。

分配原则尽量保证每个主库运行在不同的ip,每个主库和从库不在一个ip上,这样才能做到高可用。

什么是slots(槽)

上面“将6个节点合成一个集群”的过程中:

学新通

Redis集群内部划分了16384个slots(插槽),合并的时候,会将每个slots映射到一个master上面,比如上面3个master和slots的关系如下:

redis主节点 槽位范围
master1(端口:6379) [0-5460],插槽的位置从0开始的,0表示第1个插槽
master2(端口:6380) [5461-10922]
master3(端口:6381) [10923-16383]
slave1,slave2,slave3 从节点没有槽位,slave是用来对master做替补的

而数据库中的每个key都属于16384个slots中的其中1个,当通过key读写数据的时候,redis需要先根据key计算出key对应的slots,然后根据slots和master的映射关系找到对应的redis节点,key对应的数据就在这个节点上面。

集群中使用公式CRC16(key)384计算key属于哪个槽

在集群中录入值

#在redis-cli每次录入、查询键值,redis都会计算key对应的插槽,如果不是当前redis节点的插槽,redis会报错,并告知应前往的redis实例地址和端口,效果如下
#我们连接了6379这个实例来操作k1,这个节点发现k1的槽位在6381上面,返回了错误信息,怎么办呢?
redis-cli -h 192.168.1.100 -p 6379
192.168.1.100:6379> set k1 v1
(error) MOVED 12706 192.168.1.100:6381


#使用redis-cli客户端提供了-c参数可以解决这个问题
#表示以集群方式执行,执行命令的时候当前节点处理不了的时候,会自动将请求重定向到目标节点,被重定向到6381了
redis-cli -c -h 192.168.1.100 -p 6379
192.168.1.100:6379> set k1 v1
-> Redirected to slot [12706] located at 192.168.1.100:6381
OK
192.168.1.100:6381>


#同样,执行get会被重定向
redis-cli -c -h 192.168.1.100 -p 6379
192.168.1.100:6379> get k1
-> Redirected to slot [12706] located at 192.168.1.100:6381
"v1"
192.168.1.100:6381>


#不在一个slot下面,不能使用mget、mset等多键操作
192.168.1.100:6381> mset k1 v1 k2 v2
(error) CROSSSLOT Keys in request don't hash to the same slot
192.168.1.100:6381> mget k1 k2
(error) CROSSSLOT Keys in request don't hash to the same slot


#可以通过{}来定义组的概念,从而使key中{}内相同的键值放到一个slot中去
192.168.1.100:6381> mset k1{g1} v1 k2{g1} v2 k3{g1} v3
OK
192.168.1.100:6381> mget k1{g1} k2{g1} k3{g1}
1) "v1"
2) "v2"
3) "v3"
学新通

slot相关的一些命令

  • cluster keyslot <key>:计算key对应的slot
  • cluster coutkeysinslot <slot>:获取slot槽位中key的个数
  • cluster getkeysinslot <slot> <count> 返回count个slot槽中的键
192.168.1.100:6381> cluster keyslot k1{g1}
(integer) 13519
192.168.1.100:6381> cluster countkeysinslot 13519
(integer) 3
192.168.1.100:6381> cluster getkeysinslot 13519 3
1) "k1{g1}"
2) "k2{g1}"
3) "k3{g1}"

故障恢复

如果主节点下线,从节点是否能够提升为主节点?(注意:要等10 秒

#连接master1,然后将master1停掉
redis-cli -c -h 192.168.1.100 -p 6379
192.168.1.100:6379> shutdown
not connected>

#连接master2,看下集群节点的信息
redis-cli -c -h 192.168.1.100 -p 6380
192.168.1.100:6380> cluster nodes

输出如下:

学新通

slave1(6389)确实变成master了,而它原来的master:master1(6379)下线了。

继续:

#启动6379
redis-server /opt/cluster/redis-6379.conf
#连接master1
redis-cli -c -h 192.168.1.100 -p 6379
192.168.1.100:6379> cluster nodes

执行结果如下:

学新通

6379变成slave了,挂在了6389下面了。

如果某一段插槽的主从都宕机了,redis服务是否还能继续?

这个时候要看cluster-require-full-coverage参数的值了:

  • yes(默认值):整个集群都都无法提供服务了
  • no:宕机的这部分槽位数据全部不能使用,其他槽位正常

SpringBoot整合redis集群

1)引入redis的maven配置

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

application.properties中配置redis cluster信息

spring.redis.cluster.nodes=192.168.1.100:6379,192.168.1.100:6380,192.168.1.100:6381,192.168.1.100:6389,192.168.1.100:6390,192.168.1.100:6391
spring.redis.timeout=60000

其它的操作,基本就差不多了,不多做阐述了。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhifkekf
系列文章
更多 icon
同类精品
更多 icon
继续加载