zoukankan      html  css  js  c++  java
  • redis cluster集群详解

    前面博客我们已经学习到sentinel问题?为什么还要讲cluster呢?
    使用Redis Sentinel 模式架构的缓存体系,在使用的过程中,随着业务的增加不可避免的要对Redis进行扩容,熟知的扩容方式有两种,一种是垂直扩容,一种是水平扩容。垂直扩容表示通过加内存方式来增加整个缓存体系的容量比如将缓存大小由2G调整到4G,这种扩容不需要应用程序支持;水平扩容表示表示通过增加节点的方式来增加整个缓存体系的容量比如本来有1个节点变成2个节点,这种扩容方式需要应用程序支持。垂直扩容看似最便捷的扩容,但是受到机器的限制,一个机器的内存是有限的,所以垂直扩容到一定阶段不可避免的要进行水平扩容,如果预留出很多节点感觉又是对资源的一种浪费因为对业务的发展趋势很快预测。Redis Sentinel 水平扩容一直都是程序猿心中的痛点,因为水平扩容牵涉到数据的迁移。迁移过程一方面要保证自己的业务是可用的,一方面要保证尽量不丢失数据所以数据能不迁移就尽量不迁移。针对这个问题,Redis Cluster就应运而生了,下面简单介绍一下RedisCluster。
    Redis Cluster是Redis的分布式解决方案,在Redis 3.0版本正式推出的,有效解决了Redis分布式方面的需求。当遇到单机内存、并发、流量等瓶颈时,可以采用Cluster架构达到负载均衡的目的。分布式集群首要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整个数据的一个子集。Redis Cluster采用哈希分区规则中的虚拟槽分区。虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把所有的数据映射到一个固定范围内的整数集合,整数定义为槽(slot)。Redis Cluster槽的范围是0 ~ 16383。槽是集群内数据管理和迁移的基本单位。采用大范围的槽的主要目的是为了方便数据的拆分和集群的扩展,每个节点负责一定数量的槽。Redis Cluster采用虚拟槽分区,所有的键根据哈希函数映射到0 ~ 16383,计算公式:slot = CRC16(key)&16383。每一个实节点负责维护一部分槽以及槽所映射的键值数据。
     

    Redis集群

     
     
    高性能:
     
    基于KEY进行数据拆分
     
    1、在多分片节点中,将16384个槽位,均匀分布到多个分片节点中
    2、存数据时,将key做crc16(key),然后和16384进行取模,得出槽位值(0-16383之间)
    3、根据计算得出的槽位值,找到相对应的分片节点的主节点,存储到相应槽位上
    4、如果客户端当时连接的节点不是将来要存储的分片节点,分片集群会将客户端连接切换至真正存储节点进行数据存储
     
    高可用:
    在搭建集群时,会为每一个分片的主节点,对应一个从节点,实现slaveof的功能,同时当主节点down,实现类似于sentinel的自动failover的功能。
     
    Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation)。
    Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令需要在多个 Redis 节点之间移动数据, 并且在高负载的情况下, 这些命令将降低 Redis 集群的性能, 并导致不可预测的行为。
    Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
    将数据自动切分(split)到多个节点的能力。
    当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力。
     

    Redis集群数据共享

    Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含 16384 个哈希槽(hash slot), 数据库中的每个键都属于这 16384 个哈希槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。
    节点 A 负责处理 0 号至 5500 号哈希槽。
    节点 B 负责处理 5501 号至 11000 号哈希槽。
    节点 C 负责处理 11001 号至 16384 号哈希槽。
     

    槽的计算公式

    集群使用公式 CRC16(key) & 16383 计算键 key属于哪个槽。

    运行机制

    所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
    节点的fail是通过集群中超过半数的master节点检测失效时才生效.
    客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
    把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->key
     

    集群复制

     
    为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下, 仍然可以正常运作, Redis 集群对节点使用了主从复制功能: 集群中的每个节点都有 1 个至 N 个复制品(replica), 其中一个复制品为主节点(master), 而其余的 N-1 个复制品为从节点(slave)。
      在之前列举的节点 A 、B 、C 的例子中, 如果节点 B 下线了, 那么集群将无法正常运行, 因为集群找不到节点来处理 5501 号至 11000 号的哈希槽。
      假如在创建集群的时候(或者至少在节点 B 下线之前), 我们为主节点 B 添加了从节点 B1 , 那么当主节点 B 下线的时候, 集群就会将 B1 设置为新的主节点, 并让它代替下线的主节点 B , 继续处理 5501 号至 11000 号的哈希槽, 这样集群就不会因为主节点 B 的下线而无法正常运作了。
      不过如果节点 B 和 B1 都下线的话, Redis 集群还是会停止运作。
      集群的复制特性重用了 SLAVEOF 命令的代码,所以集群节点的复制行为和 SLAVEOF 命令的复制行为完全相同。
     
     

    集群的故障转移

     
    •在集群里面,节点会对其他节点进行下线检测。
    •当一个主节点下线时,集群里面的其他主节点负责对下线主节点进行故障移。
    •换句话说,集群的节点集成了下线检测和故障转移等类似 Sentinel 的功能。
    •因为 Sentinel 是一个独立运行的监控程序,而集群的下线检测和故障转移等功能是集成在节点里面的,它们的运行模式非常地不同,所以尽管这两者的功能很相似,但集群的实现没有重用 Sentinel 的代码。
     
     

    在集群里面执行命令的两种情况

     
    •命令发送到了正确的节点:命令要处理的键所在的槽正好是由接收命令的节点负责,那么该节点执行命令,就像单机 Redis 服务器一样。
    •命令发送到了错误的节点:接收到命令的节点并非处理键所在槽的节点,那么节点将向客户端返回一个转向(redirection)错误,告知客户端应该到哪个节点去执行这个命令,客户端会根据错误提示的信息,重新向正确的节点发送命令。
     

    命令发送给正确的节点

    键 date 位于 2022 槽,该槽由节点 7000 负责,命令会直接执行。

    命令发送给了错误的节点

    键 date 位于 2022 槽,该槽由节点 7000 负责,但错误发送到了7001节点

    转向错误的实现(1)

    集群中的节点会互相告知对方,自己负责处理哪些槽。
     

    转向错误的实现(2)

    集群中的每个节点都会记录 16384 个槽分别由哪个节点负责,从而形成一个“槽表”(slot table)。
    节点在接收到命令请求时,会通过槽表检查键所在的槽是否由本节点处理:
    - 如果是的话,那么节点直接执行命令;
    - 如果不是的话,那么节点就从槽表里面提取出正确节点的地址信息,然后返回转向错误。
     

    redis cluster集群的搭建

    规划、搭建过程:
     
    6个redis实例,一般会放到3台硬件服务器
    注:在企业规划中,一个分片的两个节点,分到不同的物理机,防止硬件主机宕机造成的整个分片数据丢失。

    主机名
    ip
    操作系统
    redis版本
    实例规划
    docker-01
    10.0.0.130
    centos7.4
    5.05稳定版
    /data/7000 master
    /data/7001 slave
    docker-02
    10.0.0.131
    centos7.4
    5.05稳定版
    /data/7002 master
    /data/7003 slave
    docker-03
    10.0.0.132
    centos7.4
    5.05稳定版
    /data/7004 master
    /data/7005 slave
    注意: 每台服务器上的两个实例不能互为主从,否则如果服务器挂掉就会导致集群中一个节点数据的丢失,应该让每台服务器他们彼此互为主从,这里我们规划如下
    docker-01 7000 master ---> docker-02 7003 slave
    docker-02 7002 master ---> docker-03 7005 slave
    docker-03 7004 master ---> docker-01 7001 slave

    1. 安装集群插件(redis5不用安装插件)

    EPEL源安装ruby支持
    yum install ruby rubygems -y
    使用国内源
    gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
    gem install redis -v 3.3.3
    gem sources -l
    如果无法使用,可以使用aliyun
    gem sources -a http://mirrors.aliyun.com/rubygems/
    gem sources  --remove http://rubygems.org/
     
    注意对于新版redis5 (已经出稳定版了)中已经把这个插件嵌入到了redis-cli中了,无需我们安装这个插件。下面为官方的说明:
    如果您使用的是Redis 5,这很容易实现,因为嵌入到中的Redis Cluster命令行实用程序redis-cli将为我们提供帮助,该实用程序可用于创建新集群,检查或重新分片现有集群等。

    2. 集群节点的准备

     
    在每一个服务器节点安装规划创建好目录
    mkdir /data/700{0..5}
     
    vim /data/7000/redis.conf
    port 7000
    daemonize yes
    pidfile /data/7000/redis.pid
    loglevel notice
    logfile "/data/7000/redis.log"
    dbfilename dump.rdb
    dir /data/7000
    protected-mode no
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes
    

      

    vim /data/7001/redis.conf
    port 7001
    daemonize yes
    pidfile /data/7001/redis.pid
    loglevel notice
    logfile "/data/7001/redis.log"
    dbfilename dump.rdb
    dir /data/7001
    protected-mode no
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes
    

     

    vim /data/7002/redis.conf
    port 7002
    daemonize yes
    pidfile /data/7002/redis.pid
    loglevel notice
    logfile "/data/7002/redis.log"
    dbfilename dump.rdb
    dir /data/7002
    protected-mode no
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes
    

      

    vim /data/7003/redis.conf
    port 7003
    daemonize yes
    pidfile /data/7003/redis.pid
    loglevel notice
    logfile "/data/7003/redis.log"
    dbfilename dump.rdb
    dir /data/7003
    protected-mode no
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes
    

      

    vim /data/7004/redis.conf
    port 7004
    daemonize yes
    pidfile /data/7004/redis.pid
    loglevel notice
    logfile "/data/7004/redis.log"
    dbfilename dump.rdb
    dir /data/7004
    protected-mode no
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes
    

      

    vim /data/7005/redis.conf
    port 7005
    daemonize yes
    pidfile /data/7005/redis.pid
    loglevel notice
    logfile "/data/7005/redis.log"
    dbfilename dump.rdb
    dir /data/7005
    protected-mode no
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes
     
    Redis 集群由多个运行在集群模式(cluster mode)下的 Redis 实例组成, 实例的集群模式需要通过配置来开启, 开启集群模式的实例将可以使用集群特有的功能和命令。
    以下是一个包含了最少选项的集群配置文件示例:
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes
    

      

    3. 启动节点并验证

    redis-server /data/7000/redis.conf 
    redis-server /data/7001/redis.conf 
    redis-server /data/7002/redis.conf 
    redis-server /data/7003/redis.conf 
    redis-server /data/7004/redis.conf 
    redis-server /data/7005/redis.conf 
    
    [root@docker-01 ~]# ps -ef|grep -v grep |grep redis
    root      74891      1  0 07:15 ?        00:00:01 redis-server *:7000 [cluster]
    root      75699      1  0 07:16 ?        00:00:00 redis-server *:7001 [cluster]
    
    [root@docker-02 ~]# ps -ef|grep -v grep |grep redis
    root       6411      1  0 07:17 ?        00:00:00 redis-server *:7002 [cluster]
    root       6416      1  0 07:17 ?        00:00:00 redis-server *:7003 [cluster]
    
    [root@docker-03 ~]# ps -ef|grep -v grep |grep redis
    root      17074      1  0 07:17 ?        00:00:00 redis-server *:7004 [cluster]
    root      17079      1  0 07:18 ?        00:00:00 redis-server *:7005 [cluster]
    

      

    4. 创建集群(将节点加入集群)

    redis-cli --cluster create --cluster-replicas 1 10.0.0.130:7000 10.0.0.131:7002 10.0.0.132:7004 10.0.0.131:7003 10.0.0.132:7005 10.0.0.130:7001
    给定 redis-cli 程序的命令是 create , 这表示我们希望创建一个新的集群。
    选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
    创建时会自动把前面三个节点作为主节点,后面三个作为从节点, 主节点和从节点一一对应
     
    redis3建集群的命令(reidis5已经把这个插件集成到了redis-cli中了)
    {redis_src_home}/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001
    127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
     
     
    主从对应刚好跟我们预想的一样,后面问是否要设置成上面的配置? 这里输入yes
    集群创建成功了
     

    5. 集群节点状态查看

     
    集群主节点状态
    redis-cli -p 7000 cluster nodes | grep master
    集群从节点状态
    redis-cli -p 7000 cluster nodes | grep slave
     
     
    总共有三对:master和slave一一对应,符合预期.
     
    也可以这样查看
    [root@docker-01 ~]# redis-cli -p 7000 info replication
    # Replication
    role:master
    connected_slaves:1
    slave0:ip=10.0.0.131,port=7003,state=online,offset=1540,lag=1
    ....
     
     

    集群客户端

    redis-cli -c -p 7000
    set foo bar
    get foo
     
    #注意: 客户端进行操作的时候最好要加-c, 确保是集群模式,否则有时无法进行操作.因为就是因为-c参数可以保证在操作的客户端如果没有要找的node的话,会自动转发过去,从而获取到想要的结果,
     
    重新分片
    ./redis-trib.rb reshard 127.0.0.1:7000
     
     

    集群管理

    集群主节点状态
    redis-cli -p 7000 cluster nodes | grep master
    集群从节点状态
    redis-cli -p 7000 cluster nodes | grep slave
     
    增加新的节点
    ./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
     
    删除一个节点
    redis-trib  del-node  ip:port  '<node-id>' 
    删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点
     
    添加一个从节点
    ./redis-trib.rb add-node  --slave  --master-id  $[nodeid] 127.0.0.1:7008 127.0.0.1:7000  
     
     

    增加节点

    一个新的节点需要至少一个从节点,这里我们在docker-01上添加
     

    1. 准备工作

    mkdir /data/7006
    mkdir /data/7007
     
     
    vim /data/7006/redis.conf
    port 7006
    daemonize yes
    pidfile /data/7006/redis.pid
    loglevel notice
    logfile "/data/7006/redis.log"
    dbfilename dump.rdb
    dir /data/7006
    protected-mode no
    cluster-enabled yes
    cluster-config-file nodes.conf # 添加好集群之后会保存集群的信息
    cluster-node-timeout 5000
    appendonly yes
    

      

    vim /data/7007/redis.conf
    port 7007
    daemonize yes
    pidfile /data/7007/redis.pid
    loglevel notice
    logfile "/data/7007/redis.log"
    dbfilename dump.rdb
    dir /data/7007
    protected-mode no
    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes
    

      

    redis-server /data/7006/redis.conf
    redis-server /data/7007/redis.conf
     

    2.  添加主节点

     
    redis-cli --cluster add-node 10.0.0.130:7006 10.0.0.130:7000
    add-node命令将新节点的地址指定为第一个参数,并将集群中随机存在的节点(已经存在主从节点都可以)的地址指定为第二个参数
     
    验证新节点是否已经加入集群
    [root@docker-01 7006]# redis-cli -c -p 7000 cluster nodes | egrep 7006
    623aaa030690211b641c08f6623f5b4468bf03b0 10.0.0.130:7006@17006 master - 0 1569460664357 0 connected
     
    已经成功添加到新的集群当中了.
     
    请注意,由于此节点已经连接到集群,因此它已经能够正确重定向客户端查询,并且通常来说是集群的一部分。但是,与其他master相比,它有两个特点:
    • 由于没有分配的哈希槽,因此不保存任何数据。
    • 因为它是没有分配插槽的主机,所以当从机要成为主机时,它不会参与选举过程。
    所以我们需要为新添加的节点分配槽位(重新分片), 新节点才能被使用.
     
    redis5 之前的版本添加方式
    redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
     

    3. 转移slot(重新分片)

    redis-cli --cluster reshard 10.0.0.130:7006 # 会进行交互式

    >>> Performing Cluster Check (using node 10.0.0.130:7006)
    M: 623aaa030690211b641c08f6623f5b4468bf03b0 10.0.0.130:7006
       slots: (0 slots) master
    S: 8afb9a41f361e087cea56d3912b180db043fa6f7 10.0.0.132:7005
       slots: (0 slots) slave
       replicates b537e21aa9db60d2935f47bbd88a9ebd62168b16
    S: c7f34873785eeddda818a4d1adce775cc3d01b1c 10.0.0.131:7003
       slots: (0 slots) slave
       replicates a59225315c983972554cd34e63336adad78001d6
    M: b537e21aa9db60d2935f47bbd88a9ebd62168b16 10.0.0.131:7002
       slots:[5461-10922] (5462 slots) master
       1 additional replica(s)
    S: b5ed868eebf22825fd06888c7ebb426caab2a368 10.0.0.130:7001
       slots: (0 slots) slave
       replicates a9b353fe6e31b6cea4005215648f2c4ab6731f10
    M: a9b353fe6e31b6cea4005215648f2c4ab6731f10 10.0.0.132:7004
       slots:[10923-16383] (5461 slots) master
       1 additional replica(s)
    M: a59225315c983972554cd34e63336adad78001d6 10.0.0.130:7000
       slots:[0-5460] (5461 slots) master
       1 additional replica(s)
    [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)? 4096
    

    问你要为新节点分配多少个槽位?有现在有一个有4个节点了16384/4=4096, 所以这里我们填4096

    What is the receiving node ID? 623aaa030690211b641c08f6623f5b4468bf03b0
    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: all
    

    问要接受分片的node的id, 新加节点7006: 623aaa030690211b641c08f6623f5b4468bf03b0

    问从哪个节点作为源分配槽位ID,这里选择: all, 即从已经存在所有的节点进行分配.
    Do you want to proceed with the proposed reshard plan (yes/no)?
    

    问是否从这些节点进行分配, 输入 yes

    4. 验证主节点是否添加成功

    可见新的redis 7006 已经从原有的三个节点平均分配了槽位累计刚好4096个

    redis5 之前的版本重新分片

    redis-trib.rb reshard 127.0.0.1:7000

    5. 添加从节点

    redis-cli --cluster add-node --cluster-slave --cluster-master-id 623aaa030690211b641c08f6623f5b4468bf03b0 10.0.0.130:7007 10.0.0.130:7006
    参数说明:
    --cluster-master-Id 指定要把从节点添加给哪个redis主节点的id
    10.0.0.130:7007 要添加的从节点
    10.0.0.130:7006 已经存在主节点7006

    验证:

    [root@docker-01 ~]# redis-cli -c -p 7000 cluster nodes |egrep '700[67]'
    623aaa030690211b641c08f6623f5b4468bf03b0 10.0.0.130:7006@17006 master - 0 1569462389467 7 connected 0-1364 5461-6826 10923-12287
    4ca37b1856b63ace09632a79b6788cccc47963ab 10.0.0.130:7007@17007 slave 623aaa030690211b641c08f6623f5b4468bf03b0 0 1569462387951 7 connected
    

      

    已经成功把7007从节点,添加到集群中7006的主节点上了

    注意:如果在生产环境,建议新添加的主从节点一定不要放在同一台服务器上面. 防止该服务器挂掉, 整个节点数据丢失的问题.
     
     
    redis5之前版本添加从节点写法:
    redis-trib.rb add-node --slave --master-id bff7d6e603578033f53865de3e55fb2b8c526b60 127.0.0.1:7007 127.0.0.1:7000

    删除节点

    redis-cli --cluster reshard 10.0.0.130:7006
     
    redis5之前的版本写法:
    redis-trib.rb reshard 127.0.0.1:7000
     
     
    删除一个节点
     
    主节点删除:
    删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点
     
    (1) 重新分片
     
    这里我们要把源redis 7006节点上面的4096个槽位,分配到redis 7000上面
    所以接受slot的node ID写上redis 7000的ID
    下面会让你输入你要从把那个节点的slot重新分? 这里当然是redis 7006的ID
    done代表已经输入完
     
    下一行是让你确认是否要分片,输入yes
     
    验证分片:
    [root@docker-01 ~]# redis-cli -c -p 7000 cluster nodes
    623aaa030690211b641c08f6623f5b4468bf03b0 10.0.0.130:7006@17006 master - 0 1569465429000 7 connected
    c7f34873785eeddda818a4d1adce775cc3d01b1c 10.0.0.131:7003@17003 slave a59225315c983972554cd34e63336adad78001d6 0 1569465429000 8 connected
    a9b353fe6e31b6cea4005215648f2c4ab6731f10 10.0.0.132:7004@17004 master - 0 1569465428000 3 connected 12288-16383
    8afb9a41f361e087cea56d3912b180db043fa6f7 10.0.0.132:7005@17005 slave b537e21aa9db60d2935f47bbd88a9ebd62168b16 0 1569465429548 5 connected
    a59225315c983972554cd34e63336adad78001d6 10.0.0.130:7000@17000 myself,master - 0 1569465429000 8 connected 0-6826 10923-12287
    b537e21aa9db60d2935f47bbd88a9ebd62168b16 10.0.0.131:7002@17002 master - 0 1569465428000 2 connected 6827-10922
    b5ed868eebf22825fd06888c7ebb426caab2a368 10.0.0.130:7001@17001 slave a9b353fe6e31b6cea4005215648f2c4ab6731f10 0 1569465429953 6 connected
    4ca37b1856b63ace09632a79b6788cccc47963ab 10.0.0.130:7007@17007 slave a59225315c983972554cd34e63336adad78001d6 0 1569465428000 8 connected
    [root@docker-01 ~]# 
    [root@docker-01 ~]# 
    [root@docker-01 ~]# 
    [root@docker-01 ~]# redis-cli -c -p 7007 info replication
    # Replication
    role:slave
    master_host:10.0.0.130
    master_port:7000
    master_link_status:up
    ....
    

    我通过集群状态可以看出redis 7006已经没有slot了. 之前的集群从节点 redis 7007已经指定到 集群节点redis 7000上面了,因为我们把原来redis 7006所有的slot全部迁移到了redis 7000上面了.

    (2). 开始删除主节点
    redis-cli --cluster del-node 10.0.0.130:7006 623aaa030690211b641c08f6623f5b4468bf03b0
     
    redis5 之前版本的写法
    redis-trib.rb del-node 127.0.0.1:7006 bff7d6e603578033f53865de3e55fb2b8c526b6
     
    验证: redis-cli -c -p 7000 cluster nodes
     
     

    从节点删除:
    redis-cli --cluster del-node 10.0.0.130:7007 4ca37b1856b63ace09632a79b6788cccc47963ab
     
    redis5 之前版本的写法
    redis-trib.rb del-node 127.0.0.1:7007 2af3da4252ad1a7334d476e1b56498b85a1b488c
     
    验证: redis-cli -c -p 7000 cluster nodes

     

    redis集群故障切换测试

    接着上面

    [root@docker-01 ~]# redis-cli -c -p 7000 cluster nodes
    c7f34873785eeddda818a4d1adce775cc3d01b1c 10.0.0.131:7003@17003 slave a59225315c983972554cd34e63336adad78001d6 0 1569466576000 8 connected
    a9b353fe6e31b6cea4005215648f2c4ab6731f10 10.0.0.132:7004@17004 master - 0 1569466577000 3 connected 12288-16383
    8afb9a41f361e087cea56d3912b180db043fa6f7 10.0.0.132:7005@17005 slave b537e21aa9db60d2935f47bbd88a9ebd62168b16 0 1569466577000 5 connected
    a59225315c983972554cd34e63336adad78001d6 10.0.0.130:7000@17000 myself,master - 0 1569466576000 8 connected 0-6826 10923-12287
    b537e21aa9db60d2935f47bbd88a9ebd62168b16 10.0.0.131:7002@17002 master - 0 1569466577730 2 connected 6827-10922
    b5ed868eebf22825fd06888c7ebb426caab2a368 10.0.0.130:7001@17001 slave a9b353fe6e31b6cea4005215648f2c4ab6731f10 0 1569466577529 6 connected
    

      

    关闭主库测试

     
    我把reids 7000 杀死
    [root@docker-01 ~]# ps -ef|grep redis
    root      74891      1  0 07:15 ?        00:01:32 redis-server *:7000 [cluster]
    root      75699      1  0 07:16 ?        00:01:27 redis-server *:7001 [cluster]
    root      82424  46420  0 10:56 pts/0    00:00:00 grep --color=auto redis
    [root@docker-01 ~]# kill 74891
    [root@docker-01 ~]# ps -ef|grep redis
    root      75699      1  0 07:16 ?        00:01:27 redis-server *:7001 [cluster]
    root      82842  46420  0 10:57 pts/0    00:00:00 grep --color=auto redis
    

      

    我在docker03上(也可以在docker02)查看下日志
    [root@docker-03 ~]# tail -f /data/700*/redis.log
    ==> /data/7004/redis.log <==
    17074:M 26 Sep 2019 07:48:50.222 * Background saving started by pid 17098
    17098:C 26 Sep 2019 07:48:50.264 * DB saved on disk
    17098:C 26 Sep 2019 07:48:50.265 * RDB: 2 MB of memory used by copy-on-write
    17074:M 26 Sep 2019 07:48:50.272 * Background saving terminated with success
    17074:M 26 Sep 2019 07:48:50.272 # Cluster state changed: ok
    17074:M 26 Sep 2019 07:48:50.272 * Synchronization with replica 10.0.0.130:7001 succeeded
    17074:M 26 Sep 2019 10:57:23.966 * Marking node a59225315c983972554cd34e63336adad78001d6 as failing (quorum reached).
    17074:M 26 Sep 2019 10:57:23.966 # Cluster state changed: fail
    17074:M 26 Sep 2019 10:57:24.205 # Failover auth granted to c7f34873785eeddda818a4d1adce775cc3d01b1c for epoch 9
    17074:M 26 Sep 2019 10:57:24.213 # Cluster state changed: ok
    
    ==> /data/7005/redis.log <==
    17099:C 26 Sep 2019 07:48:50.437 * Parent agreed to stop sending diffs. Finalizing AOF...
    17099:C 26 Sep 2019 07:48:50.437 * Concatenating 0.00 MB of AOF diff received from parent.
    17099:C 26 Sep 2019 07:48:50.437 * SYNC append only file rewrite performed
    17099:C 26 Sep 2019 07:48:50.437 * AOF rewrite: 4 MB of memory used by copy-on-write
    17079:S 26 Sep 2019 07:48:50.524 * Background AOF rewrite terminated with success
    17079:S 26 Sep 2019 07:48:50.524 * Residual parent diff successfully flushed to the rewritten AOF (0.00 MB)
    17079:S 26 Sep 2019 07:48:50.524 * Background AOF rewrite finished successfully
    17079:S 26 Sep 2019 10:57:23.966 * FAIL message received from b537e21aa9db60d2935f47bbd88a9ebd62168b16 about a59225315c983972554cd34e63336adad78001d6
    17079:S 26 Sep 2019 10:57:23.966 # Cluster state changed: fail
    17079:S 26 Sep 2019 10:57:24.213 # Cluster state changed: ok
    

      

    通过日志可以看出, redis cluster已经把这个节点的主的权限交给了c7f34873785eeddda818a4d1adce775cc3d01b1c, 而这个ID是10.0.0.131 redis 7003, 刚好为 redis 7000的从库的ID
     
    查看集群状态
    [root@docker-02 ~]# redis-cli -c -p 7002 cluster nodes
    b5ed868eebf22825fd06888c7ebb426caab2a368 10.0.0.130:7001@17001 slave a9b353fe6e31b6cea4005215648f2c4ab6731f10 0 1569467232651 6 connected
    8afb9a41f361e087cea56d3912b180db043fa6f7 10.0.0.132:7005@17005 slave b537e21aa9db60d2935f47bbd88a9ebd62168b16 0 1569467232551 5 connected
    a59225315c983972554cd34e63336adad78001d6 10.0.0.130:7000@17000 master,fail - 1569466638301 1569466637597 8 disconnected
    b537e21aa9db60d2935f47bbd88a9ebd62168b16 10.0.0.131:7002@17002 myself,master - 0 1569467231000 2 connected 6827-10922
    a9b353fe6e31b6cea4005215648f2c4ab6731f10 10.0.0.132:7004@17004 master - 0 1569467233663 3 connected 12288-16383
    c7f34873785eeddda818a4d1adce775cc3d01b1c 10.0.0.131:7003@17003 master - 0 1569467232000 9 connected 0-6826 10923-12287
    

    此时源docker01的redis 7000的从库 docker-02 redis 7003已经提升为了主库

     

    重新启动主库测试

    redis-server /data/7000/redis.conf
     
    查看集群状态
    [root@docker-02 ~]# redis-cli -c -p 7002 cluster nodes
    b5ed868eebf22825fd06888c7ebb426caab2a368 10.0.0.130:7001@17001 slave a9b353fe6e31b6cea4005215648f2c4ab6731f10 0 1569467495195 6 connected
    8afb9a41f361e087cea56d3912b180db043fa6f7 10.0.0.132:7005@17005 slave b537e21aa9db60d2935f47bbd88a9ebd62168b16 0 1569467496503 5 connected
    a59225315c983972554cd34e63336adad78001d6 10.0.0.130:7000@17000 slave c7f34873785eeddda818a4d1adce775cc3d01b1c 0 1569467495000 9 connected
    b537e21aa9db60d2935f47bbd88a9ebd62168b16 10.0.0.131:7002@17002 myself,master - 0 1569467494000 2 connected 6827-10922
    a9b353fe6e31b6cea4005215648f2c4ab6731f10 10.0.0.132:7004@17004 master - 0 1569467496201 3 connected 12288-16383
    c7f34873785eeddda818a4d1adce775cc3d01b1c 10.0.0.131:7003@17003 master - 0 1569467495000 9 connected 0-6826 10923-12287
    

      

    通过集群状态可以看出重新启动的原redis主库, 已经变为从库.
     
    也就是说当在redis cluster中,如果一个主库redis实例宕掉的话, 那么的它的从库将被提升为主库. 当主库再次上线时,它将成为原来从库(现在是主库)的从库.

  • 相关阅读:
    LeetCode
    LeetCode
    Centos7防火墙快速开放端口配置方法
    SQLServer2008R2无人值守批处理脚本自动化安装
    sql server2014企业版无人值守批处理脚本自动化安装
    什么是Docker?
    安全终端模拟工具Xshell 5使用密钥认证登录配置详细教程
    SVN服务端VisualSVN数据转移说明
    RTX服务端用户数据迁移说明
    win7系统保护配置现错误“文件名、目录名或卷标语法不正确。(0x8007007B)
  • 原文地址:https://www.cnblogs.com/yang-ning/p/11642850.html
Copyright © 2011-2022 走看看