• Redis_10_Redis集群实现RedisCluster应对大数据量


    一、前言

    问题:单机Redis会有瓶颈,那你们是怎么解决这个瓶颈的?

    回答:集群(永远的永远,处理单机的性能瓶颈就是分布式集群架构,Redis也是这样)

    解释:在Redis中,使用的集群的部署方式也就是Redis cluster,并且是主从同步读写分离,类似Mysql 的主从同步,Redis cluster 支撑 N 个 Redis master node,每个master node都可以挂载多个 slave node。这样整个 Redis 就可以横向扩容了。如果你要支撑更大数据量的缓存,那就横向扩容更多的 master 节点,每个 master 节点就能存放更多的数据了。

    二、CentOS 7 单机安装Redis Cluster6.0.9(3主3从伪集群)

    2.1 CentOS 7 单机安装Redis Cluster6.0.9(3主3从伪集群)

    为了节省机器,我们直接把6个Redis实例安装在同一台机器上(3主3从),只是使用不同的端口号。
    机器IP 192.168.100.138
    可以跟单机的redis安装在同一台机器上,因为数据目录不同,没有影响。

    cd /usr/local/soft/redis-6.0.9
    mkdir redis-cluster
    cd redis-cluster
    mkdir 7291 7292 7293 7294 7295 7296
    
    • 1
    • 2
    • 3
    • 4

    复制redis配置文件到7291目录

    cp /usr/local/soft/redis-6.0.9/redis.conf /usr/local/soft/redis-6.0.9/redis-cluster/7291
    
    • 1

    修改7291的redis.conf配置文件,内容:

    cd /usr/local/soft/redis-6.0.9/redis-cluster/7291
    vim redis.conf
    
    • 1
    • 2
    port 7291
    daemonize yes
    protected-mode no
    dir /usr/local/soft/redis-6.0.9/redis-cluster/7291/
    cluster-enabled yes
    cluster-config-file nodes-7291.conf
    cluster-node-timeout 5000
    appendonly yes
    pidfile /var/run/redis_7291.pid
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意,外网集群要添加这个配置(如果是自己vmware安装就不需要):

    # 实际给各节点网卡分配的IP(公网IP)
    cluster-announce-ip 47.xx.xx.xx
    # 节点映射端口
    cluster-announce-port ${PORT}
    # 节点总线端口
    cluster-announce-bus-port 1${PORT}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    把7291下的redis.conf复制到其他5个目录。

    cd /usr/local/soft/redis-6.0.9/redis-cluster/7291
    cp redis.conf ../7292
    cp redis.conf ../7293
    cp redis.conf ../7294
    cp redis.conf ../7295
    cp redis.conf ../7296
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    批量替换内容

    cd /usr/local/soft/redis-6.0.9/redis-cluster
    sed -i 's/7291/7292/g' 7292/redis.conf
    sed -i 's/7291/7293/g' 7293/redis.conf
    sed -i 's/7291/7294/g' 7294/redis.conf
    sed -i 's/7291/7295/g' 7295/redis.conf
    sed -i 's/7291/7296/g' 7296/redis.conf
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    启动6个Redis节点

    cd /usr/local/soft/redis-6.0.9/
    ./src/redis-server redis-cluster/7291/redis.conf
    ./src/redis-server redis-cluster/7292/redis.conf
    ./src/redis-server redis-cluster/7293/redis.conf
    ./src/redis-server redis-cluster/7294/redis.conf
    ./src/redis-server redis-cluster/7295/redis.conf
    ./src/redis-server redis-cluster/7296/redis.conf
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    是否启动了6个进程

    ps -ef|grep redis
    
    • 1

    六个进程都启动起来了,但是现在它们六个都是独立运行的,需要将他们关联起来,三主三从结构

    redisCluster的引入解决了 高并发、高可用、大数据量 三个问题。
    三主结构:使用三个机器来存放所有数据,保证大数据量水平扩展
    三主就有三从:一个主节点就带有一个从节点,保证了主从复制/读写分离,保证高并发
    三主就有三从:一个主节点就带有一个从节点,主节点宕机后从节点顶上,保证高可用
    六个节点变成了三主三从是因为 redis-cli --cluster create 命令中,指定 --cluster-replicas 1 表示一个主节点只有一个从节点,所以 6 /2 = 3个主节点

    cd /usr/local/soft/redis-6.0.9/src/
    redis-cli --cluster create 192.168.100.138:7291 192.168.100.138:7292 192.168.100.138:7293 192.168.100.138:7294 192.168.100.138:7295 192.168.100.138:7296 --cluster-replicas 1
    
    • 1
    • 2

    注意执行 redis-cli --cluster create 命令的时候,用绝对IP,不要用127.0.0.1

    Redis会给出一个预计的方案,对6个节点分配3主3从,如果认为没有问题,输入yes确认

    批量写入值

    cd /usr/local/soft/redis-6.0.9/redis-cluster/
    vim setkey.sh
    
    • 1
    • 2

    脚本内容

    #!/bin/bash
    for ((i=0;i<20000;i++))
    do
    echo -en "helloworld" | redis-cli -h 192.168.44.181 -p 7291 -c -x set name$i >>redis.log
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    chmod +x setkey.sh
    ./setkey.sh
    
    • 1
    • 2

    连接到客户端

    redis-cli -p 7291
    redis-cli -p 7292
    redis-cli -p 7293
    
    • 1
    • 2
    • 3

    每个节点分布的数据

    127.0.0.1:7291> dbsize
    (integer) 6652
    127.0.0.1:7292> dbsize
    (integer) 6683
    127.0.0.1:7293> dbsize
    (integer) 6665
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2.2 实践:redisCluster 安装

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    执行完创建集群之后,就往这个三主三从的集群里面插入数据,如下:
    在这里插入图片描述

    在这里插入图片描述

    2.3 redisCluster管理命令

    cluster管理命令
    其他命令,比如添加节点、删除节点,重新分布数据:

    redis-cli --cluster help
    Cluster Manager Commands:
      create         host1:port1 ... hostN:portN
                     --cluster-replicas <arg>
      check          host:port
                     --cluster-search-multiple-owners
      info           host:port
      fix            host:port
                     --cluster-search-multiple-owners
      reshard        host:port
                     --cluster-from <arg>
                     --cluster-to <arg>
                     --cluster-slots <arg>
                     --cluster-yes
                     --cluster-timeout <arg>
                     --cluster-pipeline <arg>
                     --cluster-replace
      rebalance      host:port
                     --cluster-weight <node1=w1...nodeN=wN>
                     --cluster-use-empty-masters
                     --cluster-timeout <arg>
                     --cluster-simulate
                     --cluster-pipeline <arg>
                     --cluster-threshold <arg>
                     --cluster-replace
      add-node       new_host:new_port existing_host:existing_port
                     --cluster-slave
                     --cluster-master-id <arg>
      del-node       host:port node_id
      call           host:port command arg arg .. arg
      set-timeout    host:port milliseconds
      import         host:port
                     --cluster-from <arg>
                     --cluster-copy
                     --cluster-replace
      help           
    
    For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
    附录:
    (在redis客户端执行)
    
    • 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
    • 39
    • 40

    在这里插入图片描述

    集群命令
    cluster info :打印集群的信息
    cluster nodes :列出集群当前已知的所有节点(node),以及这些节点的相关信息。
    
    • 1
    • 2
    • 3
    节点命令
    cluster meet :将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。
    cluster forget <node_id> :从集群中移除 node_id 指定的节点(保证空槽道)。
    cluster replicate <node_id> :将当前节点设置为 node_id 指定的节点的从节点。
    cluster saveconfig :将节点的配置文件保存到硬盘里面。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    槽slot命令
    cluster addslots [slot …] :将一个或多个槽(slot)指派(assign)给当前节点。
    cluster delslots [slot …] :移除一个或多个槽对当前节点的指派。
    cluster flushslots :移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。
    cluster setslot node <node_id> :将槽 slot 指派给 node_id 指定的节点,
    如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。
    cluster setslot migrating <node_id> :将本节点的槽 slot 迁移到 node_id 指定的节点中。
    cluster setslot importing <node_id> :从 node_id 指定的节点中导入槽 slot 到本节点。
    cluster setslot stable :取消对槽 slot 的导入(import)或者迁移(migrate)。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    键命令
    cluster keyslot :计算键 key 应该被放置在哪个槽上。
    cluster countkeysinslot :返回槽 slot 目前包含的键值对数量。
    cluster getkeysinslot :返回 count 个 slot 槽中的键
    
    • 1
    • 2
    • 3
    • 4

    三、Redis Cluster原理

    3.1 Redis Cluster架构

    Redis Cluster 可以看到是由多个 Redis 实例组成的数据集合。客户端不需要关注数据的自己到底存储在哪个节点,只需要关注这个集合整体。以三主三从为例,节点之间两两交互,共享数据分片、节点状态等信息。
    在这里插入图片描述

    3.2 数据分布

    Redis 既没有用哈希取模,也没有用一致性话下,而是通过虚拟槽来实现的。
    Redis 创建了 16384 个槽slot,每个节点负责一个区间的 slot 。比如节点1负责 0 -5460 ,Node2 负责 5461 - 10922 ,Node3 负责 10923 - 16383.

    在这里插入图片描述
    当然一个Redis Group节点也不一定是 1主1从,可以是 1主N从 ,如下:
    在这里插入图片描述

    对象分布到 Redis 节点的时候,对 key 使用 CRC16算法计算再 % 16384,得到一个slot的值,数据就落到负责这个slot的redis节点上。

    Redis 的每个master节点都会维护自己负责的slot。用一个bit序列实现,比如:序列的第0位是1,就代表第一个slot是它负责的;序列的第1位是0,就代表第二个slot不是它负责的。对于开发者来说,在redis-cli 连接的时候,需要指定连接那个端口,因为有了六个redis,如下:

    ./redis-cli -p 7291
    ./redis-cli -p 7292
    ./redis-cli -p 7293
    
    • 1
    • 2
    • 3

    三者联系:节点时实际使用的机器(个数),slot是16384固定不会改变,N个节点平均的管理 16384 个slot,key是通过算法直接分配到 slot 上,然后间接分配到节点上的。

    三者联系
    查看一个节点下管理哪些slot?redis-cli cluster create 命令就可以看到
    查看一个节点下管理哪些key?key * 可以看到所有键,dbsize 可以看到键的数量。
    查看一个key下在哪个slot?在redis-cli中,使用 cluster keyslot keyname 就可以得到了。

    在这里插入图片描述

    注意:就算是节点/机器增加和减少,slot的个数是不会改变的,“key通过CRC运算然后取模16384得到槽序号”这个算法也是不会改变的,所以,三者联系中,key和slot的关系是永远不会改变,某个key永远只分配到某个slot上去(无论这个key的value如何改变,除非这个key的名称发生改变,但是没有这种操作),某个slot永远只管理某些key。但是,slot和节点的关系是会发生改变,如果节点新增或减少,但是slot的数量 16384 是不变的,从而 slot 会迁移,所以一个key会从一个机器上到了另外一个机器上。

    slot对开发者不可见,开发者可见的只有 key 和 节点/机器,所以节点增加后减少,对于开发者而言,还需需要关注 一个key会从一个机器上到了另外一个机器上。

    3.3 RedisCluster让相关的数据落到同一个节点上

    问题:RedisCluster中,如何让相关的数据落到同一个节点上?这也是现实的业务需求,比如有一些 multi key 操作是不能跨节点的,例如用户 2673 的基本信息和金融信息?

    回答:在 key 里面加入{hash tag} 即可。Redis 在计算槽编号时候,只会获取 {} 之间字符串进行槽编号计算,这样由于上面两个不同的键,{} 里面的字符串是相同的,因此他们可以被计算出相同的槽。实践如下:

    在这里插入图片描述

    3.4 客户端重定向

    问题:客户端怎么知道应该连接到哪台机器上?如果访问的数据不在当前节点上,怎么办?

    127.0.0.1:7293> set aa aa1
    (error) MOVED 1180 192.168.100.138:7291
    
    • 1
    • 2

    回答:服务端返回MOVED,也就是根据 key 计算出来是slot不归当前端口管理,而是归属于 7591 端口管理,这个时候客户端应该更换连接端口,用 ./redis-cli -p 7291 操作,才会返回 OK。但是这样的会就需要客户端连接两次服务端。

    其实,Jedis 等客户端会在本地维护一份(slot,node)的映射关系。大部分时间不需要重定向,所以叫 smart jedis (需要客户端的支持)。

    Redis最常用的三个客户端:Jedis Lettuce Redission
    其中,使用redisTemplate的就是三种中选择一个使用,根据redisTemplate的不同版本选择不同的。

    3.5 数据迁移

    问题:新增或下线了Master节点,数据怎样迁移(就是重新分配slot)?
    回答:因为key和slot的关系是永远不变的,当新增了节点的时候,需要把原有的slot分配给新的节点负责,并将相关的数据迁移过来(就是将相关的key迁移过来),内部的迁移 redis 的设计者搞好了的,其实对于开发者来说,就是一行命令的事,如下:

    # 步骤1:新增一个7297端口的redis(先启动一个7297端口的redis,再使用下面这条命令加入到 RedisCluster 即可)
    ./redis-cli --cluster add-node 127.0.0.1:7291 127.0.0.1:7297
    
    # 步骤2:由于新增一个7297端口的redis还没有任何哈希槽,不能分布数据,所以在原来的人一个节点上执行
    ./redis-cli --cluster reshard 127.0.0.1:7291
    
    # 输入需要分配的哈希槽的数据(比如500),和哈希槽的来源节点(可以输入all或者id),就是这500个槽从之前哪个节点拿来。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.6 Redis Cluster 故障转移/高可用

    问题:只有主节点可以写操作,如果一个主节点宕机,从节点怎样变成主节点?
    回答:当从节点发现自己的主节点变成 fail 状态的时候,便尝试进行 failover,期望自己成为新的主节点。由于挂掉的主节点可能有多个从节点,从而存在多个从节点竞争成为主节点的过程,过程如下:

    1.slave发现自己的master变为FAIL
    2.将自己记录的集群currentEpoch1,并广播FAILOVER_AUTH_REQUEST信息
    3.其他节点收到该信息,只有master响应,判断请求者的合法性,并发送FAILOVER_AUTH_ACK,对每一个epoch只发送一次ack
    4.尝试failover的slave收集FAILOVER_AUTH_ACK
    5.超过半数后变成新Master
    6.广播Pong通知其他集群节点。

    小结:RedisCluster既能是实现主从复制,又能实现主从切换,相当于集成Replication 和Sentinel 的功能。

    3.7 Redis Cluster 特点

    Redis Cluster 特点

    1. 无中心架构。
    2. 数据按照slot存储分布在多个节点,节点间数据共享,可动态调整数据分布。
    3. 可扩展性,可线性扩展到1000个节点(官方推荐不超过1000个),节点可动态添或删除。
    4. 高可用性,部分节点不可用时,集群仍可用。通过增Slave做standby数据副本,能够实现故障自动failover,节点之间通过gossip协议交换状态信息,用投票机制完成Slave到Master的角色提。
    5. 降低运维成本,提高系统的扩展性和可用性。

    四、尾声

    redisCluster的引入解决了 高并发、高可用、大数据量 三个问题。
    三主结构:使用三个机器来存放所有数据,保证大数据量水平扩展;
    三主就有三从:一个主节点就带有一个从节点,保证了主从复制/读写分离,保证高并发;
    三主就有三从:一个主节点就带有一个从节点,主节点宕机后从节点顶上,保证高可用。

  • 相关阅读:
    springboot+vue网上学生评教系统java
    中国VOCs催化剂行业研究与投资战略报告(2022版)
    基于ChatGPT的大型语言模型试用心得
    图论03-【无权无向】-图的深度优先遍历-路径问题/检测环/二分图
    Redhat(7)-文件挂载Mount-管理cockpit-文件查找locate和find
    【LeetCode-二叉树训练】
    Python之第六章 内置容器 --- 集合
    基于STM32结合CubeMX学习Free-RT-OS的源码之任务调度
    elasticsearch配置参数详解
    【JavaScript】npm、Yarn 和 pnpm 的区别
  • 原文地址:https://blog.csdn.net/qq_36963950/article/details/126817118