• Redis集群(Cluster)


    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/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    将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/
    
    • 1
    • 2
    创建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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    创建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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    创建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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    创建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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    创建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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    创建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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    启动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信息省略
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    确保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文件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    将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
    
    • 1
    • 2
    • 3
    • 合体的命令后面会跟上所有节点的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将继续执行
    #等待执行完毕
    
    • 1
    • 2
    • 3
    • 4
    • 5
    连接集群节点,查看集群信息:cluster nodes
    #需要使用redis-cli -c命令连接集群中6个节点中任何一个节点都可以
    #注意和之前的连接参数有点不同redis-cli命令后面多了一个-c参数,表示采用集群的方式连接
    #连上以后,然后使用cluster nodes可以查看集群节点信息,如下
    192.168.1.100:6379> cluster nodes
    #信息展示省略,执行完cluster nodes,按照之前的配置会出现6条信息
    
    • 1
    • 2
    • 3
    • 4
    • 5

    截图解释一下,如下:

    在这里插入图片描述

    集群中的每个节点都会生成一个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的知识了,后面会提及
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    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)%16384计算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"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    slot相关的一些命令

    • cluster keyslot :计算key对应的slot
    • cluster coutkeysinslot :获取slot槽位中key的个数
    • cluster getkeysinslot 返回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}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    故障恢复

    如果主节点下线,从节点是否能够提升为主节点?(注意:要等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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    输出如下:

    在这里插入图片描述

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5

    执行结果如下:

    在这里插入图片描述

    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>
    
    • 1
    • 2
    • 3
    • 4

    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
    
    • 1
    • 2

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

  • 相关阅读:
    CentOS 8 通过YUM方式升级最新内核
    Z检验|T检验|样本标准差S代替总体标准差 σ
    渗透实例------2个星期艰难的渗透纪实
    Java 线程的几种状态
    前端开发工具有哪些?17款前端工程师必备工具推荐!
    【算法练习Day1】二分查找&&移除元素
    使用 Hugging Face 微调 Gemma 模型
    Destroying Bridges(Round 934)
    [NOTE] PuTTYgen generate PublicKey and Configure SSH on RedHat7
    Maven 使用IDEA环境操作
  • 原文地址:https://blog.csdn.net/lili40342/article/details/127942123