Redis集群入门

官方文章:html

https://redis.io/topics/cluster-tutorial#redis-cluster-configuration-parametersjava

 

本文永久地址:node

http://www.javashuo.com/article/p-xpfvwiyc-cr.htmlgit

 

本文档是Redis集群的简单介绍,没有涉及复杂难懂的分布式概念的赘述,只是提供了从用户角度来如何搭建测试以及使用的方法,若你打算使用并深刻了解Redis集群,推荐阅读完本章节后,仔细阅读Redis集群规范一章。本教程试图提供最终用户一个简单的关于集群和一致性特征的描述。github

 

请注意,本教程基于Redis 3.0或更高的版本。若是你计划部署集群,那么咱们建议你从阅读这个文档开始。redis

 

Redis集群基础

  Redis集群定义docker

  Redis集群提供一种redis运行方式,能将数据自动分片到多个Redis节点,且Redis集群在分区期间也提供必定的可用性,即在某些节点发生故障或没法通讯时,集群也能正常工做,但当大面积节点故障,如大多数master都不可用时,集群就不能使用了数据库

 

  从实用性角度,Redis集群提供一下功能:promise

    ·自动切割数据到多个Redis节点缓存

    ·小部分节点故障或者不可达时,集群能正常工做

 

  Redis集群TCP端口

  Redis集群中每一个节点都需侦听两个TCP端口,6379端口用于客户端通讯,客户端通讯端口加上10000(两个端口老是相差10000),如16379专用于集群总线(Cluster bus),用于节点间二进制协议的节点间通讯。各节点使用集群总线故障检测,配置更新,故障转移受权等。客户端不能使用集群总线端口

 

  请注意,为了让Redis群集正常工做,须要为每一个节点配置2个端口(必须):

    ·客户端端口(默认6379)须要对全部客户端和集群节点开放,由于集群节点须要经过该端口进行密钥迁移(keys migrations

    ·集群总线端口(客户端端口+ 10000)对集群全部节点开放便可

 

  集群总线使用不一样的二进制协议(不一样于客户端与Redis使用的协议)进行节点到节点的数据交换,此协议能够减小带宽和处理时间

 

  Redis集群和Docker

  目前,redis集群并不支持地址和端口都被从新映射的NAT环境

  Docker使用一种端口映射技术:运行在docker容器内部的程序可能使用的端口和客户端程序使用的端口不一样,这对于同一服务器中同时使用相同端口运行多个容器颇有用

  为了使DockerRedis Cluster兼容,您须要使用Docker的主机联网模式。请查看Docker文档--net=host选项以获取更多信息

 

  Redis集群数据分片

  Redis集群不使用一致性哈希,而是一种不一样的分片形式,其中每一个键在概念上都是咱们称之为哈希槽的部分

  Redis集群中有16384个哈希槽,每一个key经过CRC16校验后对16384取模来决定放置哪一个槽。

  集群中每一个节点负责哈希槽的的一个子集,如一个有3点歌节点的Redis集群:

    ·节点A包含从05500的哈希槽

    ·节点B包含从550111000的哈希槽

    ·节点C包含从1100116383的哈希槽

 

  如此便能方便地添加和删除集群中的节点。如我想添加一个新节点D,我须要将节点ABC中的一些哈希槽移动到D;一样,想删除节点A,则能够移动由A服务的散列槽到BC.当节点A将为空时,我能够将它从群集中完全删除。

  因为从一个节点将哈希槽移动到另外一个节点并不会中止服务,因此不管添加删除或者改变某个节点的哈希槽的数量都不会形成集群不可用的状态

 

  若多个key都属于一个哈希槽,那么集群能经过单个命令(或者一个完成的事务或Lua脚本执行)同时操做这些key,咱们可使用“哈希标签”(Hash tags)强制让多个key分配到同一哈希槽。“哈希标签”在Redis集群规范中有介绍,简单来讲就是若key含有大括号”{}”,则只有大括号中的字符串会被哈希,如“this{foo}another{foo}”这两个key必定会被分配到同一个哈希槽,而后在具备多个间的命令中做为参数一块儿使用。

 

  Redis集群主从模式

  为了保证在部分主master节点挂掉或不能与大多数节点通讯时保持可用性,Redis集群使用主从模式,保证每一个哈希槽都有1个到N个副本。

  上述例子咱们有节点ABC三个,若节点B故障,集群则再也不可用,且会丢失从550111000哈希槽。然而若每一个master都有一个slave,也就是说ABC三个master节点就会分别有A1B1C1三个slave节点,即便B节点挂掉,集群也不会受影响,B1复制了B的数据,此时集群将提高B1做为新master继续正常工做。但BB1同时挂掉,redis集群确定就不可用了。

 

  Redis集群对一致性的保证

  Redis集群不能保证强一致性,在架构中这意味着在某些状况下,可能会丢失向客户端返回“确认写成功”的数据

 

  丢失写入数据的第一个缘由就是redis异步复制数据,也就是说:

    ·客户端写入数据到master B

    ·master B向客户端返回“写入成功”

    ·master B传输数据到slaveB1B2B3

 

  由上可知,B在回复客户端以前不等待B1B2B3的写入完成确认,所以这会对redis形成严重的延迟损失,就像客户端写入了数据,master B确认写入,但在B将数据复制到任何一个slave前就已经挂掉,那写入将永久丢失,由于被提高为新master的任何slave都没有收到该数据。

 

  这与大多数每秒刷新数据到磁盘的数据库配置相似,也能够经过强制数据库在回复客户端前先刷新数据到磁盘来提升一致性,但这种作法性能不好,这种方式就是让Redis集群在使用同步复制。

 

  到底使用哪一种方式,要根据应用场景在性能和一致性之间有一个权衡。

 

  若真的须要,redis集群也能经过“WAIT”指令实现同步复制,这使得写入丢失的可能行大大下降,但并不意味着使用同步复制Redis集群就是强一致性了,如master还将来得及同步数据到任一slave就挂掉,或者被提高为新master没有收到同步过来的数据,都会致使不一致性的发生。使用“WAIT”只能相对的提升一致性。

 

  还有一个值得注意的场景发生在网络故障时,当客户端与少数节点(至少一个master节点)正常通讯,但与其余大多数节点网络不通。以ABCA1B1C1 三主三从组成的6个节点集群为例,另一个客户端称之为Z1。网络故障产生网络分区后,可能ACA1B1C1在一个分区,而BZ1在另外一个分区。此时B仍然能接收写入请求,Z1仍然能写入B。若分区在很短期能恢复,集群将继续正常运行,但若网络过久未恢复,网络分区持续时间太长,B1会在大多数节点都能通讯的分区里面被提高为mastermaster B在网络恢复后,会成为master B1的新slave,且丢弃Z1发送给B的写操做,而后从B1从新复制数据。

 

  节点间网络通讯断开有一个时间限制,若断开时间超过了大多数节点能容忍的长度,那就会有一个新的master被选举出来。

  这个时间被称之为节点超时(node timeout,这个时间对集群很是重要,当达到节点超时时间,master被认为已经下线,会有新master被选举出来。一样,在节点超时后,若master仍然不能联系到其余master,它将进入错误状态,并中止接收写入请求。

 

Redis集群参数配置

  先介绍redis.conf中集群的参数配置,后面会有集群部署示例。

    ·cluster-enabled yes/no #Redis集群开关。Yes表示他是集群中一个节点,no表示他是一个普通单一的redis实例

    ·cluster-config-file nodes-6379.conf #配置被称之为“集群配置文件”,但此配置文件是集群节点自动维护,不须要人工干预,每次集群配置有所变更,都会自动更新到此文件,以便节点重启时能从新加载配置。该文件列出集群中其余节点的状态,持久化的参数选项等等

    ·cluster-node-timeout 15000 #单位毫秒,集群节点可以失联的最大时间,超过该时间,该节点就会被认为故障。Master超过此时间不可达,它的slave节点就会选举出新master替代之。另外,任何节点超过此时间没有与大部分master通讯将中止接收任何请求

    ·cluster-slave-validity-factor 10 #用于限定slavemaster的失联时长的倍数。若设置0,不管slavemaster失联多久,slave都会尝试升级为master(只要slave没法与master通信,都会尝试故障转移,Cluster有选举机制,有可能会被否决),若设置为正数,则失联的最大时长为(cluster-node-timeout * cluster-slave-validity-factor),超过此时间slave不具有故障转移资格,没法被提高为master。如cluster-node-timeout5scluster-slave-validity-factor10,,当slavemaster失联超过50s后,slave就再也不具有成为master的资格。注意,若是此参数不为0,可能出现因为某master节点失联却没有slave能顶上的状况,从而致使集群不能正常工做,此时,只有等到原来的master从新回归到集群,集群才恢复正常。

    ·cluster-migration-barrier 1 #此参数保证Redis集群中不会出现裸奔的master节点,即保证每一个master节点都有slave节点。只有当一个master节点至少拥有给定数量个处于正常工做中的slave节点时,才会分配slave节点给集群中孤立的master节点。这个给定数量就是cluster-migration-barrier。给定数量是1意味着一个slave节点只有在其master节点另外至少还有一个正常工做的slave节点的状况下才会被分配(副本迁移)。那些分配后仍然剩余migration barrierslave节点的master节点才会触发副本迁移,而不是分配前有migration barrierslave节点的master节点会触发节点分配!!有关教程,请参阅本文档副本迁移部分

    ·cluster-require-full-coverage yes #在部分key所在的节点不可用时,若是此参数设置为”yes(默认值), 则整个集群中止接受操做;若是此参数设置为”no”,则集群依然为可达节点上的key提供读操做(集群是否须要全部的slot都分配给在线节点才能正常访问)

 

建立和使用Redis集群(主要两步骤:建立实例和链接实例建立集群)

  注意:手动部署一个redis集群,最主要是在学习各类操做。

  若想尽快启动并运行一个集群,能够直接看下一节“使用create-cluster脚本直接建立Redis群集”

 

  要建立一个redis集群,首要任务就是以集群模式运行几个空Redis实例,必须以集群模式运行,才能使Redis实例具备集群节点功能、支持集群节点指令

  如下是最小redis集群配置文件:

  port 7000

  cluster-enabled yes

  cluster-config-file nodes.conf

  cluster-node-timeout 5000

  appendonly yes

  

 

  Redis集群正常运行至少须要3master对于第一次测试,建议启动一个由三主三从组成的六节点群集:

 

  一、建立6个以redis实例端口名称的目录:

        mkdir -pv /usr/local/cluster-test/700{0..5}

  二、在每一个端口号目录下建立配置文件redis700{0..5}.conf,内容为上面最小redis集群配置,注意修改端口号

  三、启动6redis集群节点,建议启动6个终端分别启动:

    cd /usr/local/cluster-test/7000 ; redis-server /usr/local/cluster-test/7000/redis7000.conf &
    cd /usr/local/cluster-test/7001 ; redis-server /usr/local/cluster-test/7001/redis7001.conf &
    cd /usr/local/cluster-test/7002 ; redis-server /usr/local/cluster-test/7002/redis7002.conf &
    cd /usr/local/cluster-test/7003 ; redis-server /usr/local/cluster-test/7003/redis7003.conf &
    cd /usr/local/cluster-test/7004 ; redis-server /usr/local/cluster-test/7004/redis7004.conf &
    cd /usr/local/cluster-test/7005 ; redis-server /usr/local/cluster-test/7005/redis7005.conf &

  

    因为每一个实例都是新启动的,nodes.conf尚未自动生成,因此会发出此信息,且生成nodes.conf,都会为本身分配一个新的ID

    10390:M 31 May 14:33:58.078 * No cluster configuration found, I'm f219739744e2fca6f2e6e6c75c9c1f2caa95b05b

 

    做为此节点在整个集群中的惟一标识,生成的ID将一直被各节点使用,节点使用ID来区分其余节点而非IP+PORT,这个ID在节点的整个生命周期内都不会改变,除非节点被移除集群。这个ID咱们称之为节点IDNode ID

 

  四、此时6个集群模式的Redis实例已经运行,能够开始建立Redis集群。Ruby脚本“redis-trib”是一个可让咱们很是方便地建立Redis集群的命令行工具,该脚本用于建立新集群,状态检查,或给集群从新分片:

 

     yum install rubygems ruby
     gem install redis #若提示ruby版本太低,请查看 https://www.cnblogs.com/erbiao/p/9117018.html  。另外,若你的redis版本是4.0.X,强烈建议安装低版本的redis版本库,不然reshard时会出现语法错误。具体请查看:https://www.cnblogs.com/erbiao/p/9138604.html
     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 #“--replicas 1”表示每一个master节点须要一个slave节点。其余参数就是须要加入这个集群的redis实例的地址。执行后,redis-trib会提供一些建议的配置。       

    ... ...

    [OK] All nodes agree about slots configuration.

    >>> Check for open slots...

    >>> Check slots coverage...

    [OK] All 16384 slots covered. #表示有16384个哈希槽可用

 

    显示如上信息表示集群建立完成

  五、查看nodes.conf信息

    cat /usr/local/cluster-test/7001/nodes.conf

    06c5baf38ae368bbe8b7fef037d42026ab385590 127.0.0.1:7001@17001 myself,master - 0 1527753131000 2 connected 5461-10922

    fdc0c79f9f782b218dad297b48bde32aa0acc31f 127.0.0.1:7005@17005 slave 3fbbebd7bd822dfada7db5bde983534ff2906d4f 0 1527753131000 6 connected

    b88654ae05706a771d6f23d8877e890f99dba315 127.0.0.1:7004@17004 slave 06c5baf38ae368bbe8b7fef037d42026ab385590 0 1527753131000 5 connected

    41ec008599691424cdf8cdf9f3dc26ab1eef7050 127.0.0.1:7003@17003 slave f219739744e2fca6f2e6e6c75c9c1f2caa95b05b 0 1527753131600 4 connected

    f219739744e2fca6f2e6e6c75c9c1f2caa95b05b 127.0.0.1:7000@17000 master - 0 1527753131000 1 connected 0-5460

    3fbbebd7bd822dfada7db5bde983534ff2906d4f 127.0.0.1:7002@17002 master - 0 1527753130599 3 connected 10923-16383

    vars currentEpoch 6 lastVoteEpoch 0

 

使用脚本create-cluster建立redis集群

  上述的建立方法比较繁琐,“utils/create-cluster/create-cluster”此脚本能简化建立步骤,此脚本会调用其余redis集群命令,因此最好在utils/create-cluster中执行,或者修改脚本文件也是能够的。

  脚本utils/create-cluster/create-cluster”有默认参数,能够根据须要从新定义。

 

  如要启动一个三主三从6节点的Redis集群:

  1、命令默认生成6个集群模式的Redis实例,端口30001 ~ 30006

  cd utils/create-cluster/
   ./create-cluster start

 

  2、链接各个实例,建立Redis集群

  cd utils/create-cluster/
  ./create-cluster create

 

    [OK] All 16384 slots covered. #表示建立成功

 

  三、默认生成的文件都在当前目录,包括持久化AOF文件,日志文件,RDB数据文件(手动也会生成)

    [root@hd4 create-cluster]# ll

    总用量 92

    -rw-r--r-- 1 root root 2518 5月  31 16:27 30001.log

    -rw-r--r-- 1 root root 3683 5月  31 16:27 30002.log

    -rw-r--r-- 1 root root 3683 5月  31 16:27 30003.log

    -rw-r--r-- 1 root root 4739 5月  31 16:27 30004.log

    -rw-r--r-- 1 root root 4739 5月  31 16:27 30005.log

    -rw-r--r-- 1 root root 4739 5月  31 16:27 30006.log

    -rw-r--r-- 1 root root    0 5月  31 16:27 appendonly-30001.aof

    -rw-r--r-- 1 root root    0 5月  31 16:20 appendonly-30002.aof

    -rw-r--r-- 1 root root    0 5月  31 16:20 appendonly-30003.aof

    -rw-r--r-- 1 root root    0 5月  31 16:27 appendonly-30004.aof

    -rw-r--r-- 1 root root    0 5月  31 16:27 appendonly-30005.aof

    -rw-r--r-- 1 root root    0 5月  31 16:27 appendonly-30006.aof

    -rwxrwxr-x 1 root root 2321 2月   3 00:39 create-cluster

    -rw-r--r-- 1 root root  175 5月  31 16:27 dump-30001.rdb

    -rw-r--r-- 1 root root  175 5月  31 16:27 dump-30002.rdb

    -rw-r--r-- 1 root root  175 5月  31 16:27 dump-30003.rdb

    -rw-r--r-- 1 root root  175 5月  31 16:27 dump-30004.rdb

    -rw-r--r-- 1 root root  175 5月  31 16:27 dump-30005.rdb

    -rw-r--r-- 1 root root  175 5月  31 16:27 dump-30006.rdb

    -rw-r--r-- 1 root root  787 5月  31 16:27 nodes-30001.conf

    -rw-r--r-- 1 root root  787 5月  31 16:27 nodes-30002.conf

    -rw-r--r-- 1 root root  799 5月  31 16:27 nodes-30003.conf

    -rw-r--r-- 1 root root  799 5月  31 16:27 nodes-30004.conf

    -rw-r--r-- 1 root root  787 5月  31 16:27 nodes-30005.conf

    -rw-r--r-- 1 root root  787 5月  31 16:27 nodes-30006.conf

    -rw-rw-r-- 1 root root 1308 2月   3 00:39 README

 

  四、其余

    (1) 清除集群数据,会删除生成的全部文件,包括aof文件,日志文件,rdb文件,nodes.conf文件

    cd utils/create-cluster/
    ./create-cluster clean

  

    (2) 中止集群

    cd utils/create-cluster/
    ./create-cluster stop

  

    (3) create-cluster其余用法:

    [root@hd4 create-cluster]# create-cluster

    Usage: /usr/bin/create-cluster [start|create|stop|watch|tail|clean]

    start       -- Launch Redis Cluster instances.

    create      -- Create a cluster using redis-trib create.

    stop        -- Stop Redis Cluster instances.

    watch       -- Show CLUSTER NODES output (first 30 lines) of first node.

    tail <id>   -- Run tail -f of instance at base port + ID.

    clean       -- Remove all instances data, logs, configs.

    clean-logs  -- Remove just instances logs.

 

    (4) 解析create-cluster脚本,咱们能够根据需求修改脚本

    a. PORT=30000 #集群端口从30000开始,生成“NODES”个实例

    b. TIMEOUT=2000 #指定cluster-node-timeout

    c. NODES=6 #生成节点数量

    d. REPLICAS=1 #表示每一个master须要一个slave

 

玩转Redis集群

  现阶段Redis集群的一个问题就是现成的客户端库比较少。现知道的有以下几种:

    ·redis-rb-cluster Ruby实现,是redis-rb的简单封装,实现了与集群交互的基础功能

    ·redis-py-cluster Python实现的redis-rb-cluster接口,支持大部分redis-py功能,正处于活跃开发状态

    ·Predis 支持Redis集群,处于活跃状态

    ·Jedis java实现,最近添加了对集群的支持

    ·StackExchange.Redis 提供C#支持(且对大多数.NET语言都适用,VBF#等)

    ·thunk-redis 提供对Node.jsio.js的支持,它是支持pipelining和集群的thunk/promise-based客户端

    ·redis-go-cluster 集群工具,使用Redisgo库实现的go语言客户端,经过结果聚合实现MGET/MSET

    ·redis-cli  github中的redis不稳定分支,-c选项提供了基础的集群管理功能

 

  如下是redis-cli工具的检测测试:

    $ redis-cli -c -p 7000

    redis 127.0.0.1:7000> set foo bar

    -> Redirected to slot [12182] located at 127.0.0.1:7002

    OK

    redis 127.0.0.1:7002> set hello world

    -> Redirected to slot [866] located at 127.0.0.1:7000

    OK

    redis 127.0.0.1:7000> get foo

    -> Redirected to slot [12182] located at 127.0.0.1:7002

    "bar"

    redis 127.0.0.1:7000> get hello

    -> Redirected to slot [866] located at 127.0.0.1:7000

    "world"

 

  redis-cli实现了集群客户端最基础的功能:将客户端请求正确重定向到正确节点。如上例中,写入和读取时会自动切换到不一样节点。逻辑实现比较严谨的客户端能够缓存哈希槽到节点的映射关系,让客户端直接链接到正确的节点,只有集群配置发生改变时才刷新映射关系,如故障转移后,或者增长/删除节点。

 

  使用redis-rb-cluster”编写示例程序

  在说明如何操做Redis集群前,如故障切换或从新分片,先建立一个示例程序了解Redis集群与客户端是怎么交互的。

  咱们经过一个例子,让部分节点故障或从新分片等,来了解这实际运做中,redis集群是如何处理的。若是这期间没有客户端对集群发起写操做,将不益于咱们了解状况

  这节经过2个例子来演示redis-rb-cluster的基础用法,下面是第一个例子,源码在redis-rb-cluster目录下的example.rb文件中。

       1  require './cluster'

       2

       3  if ARGV.length != 2

       4      startup_nodes = [

       5          {:host => "127.0.0.1", :port => 7000},

       6          {:host => "127.0.0.1", :port => 7001}

       7      ]

       8  else

       9      startup_nodes = [

      10          {:host => ARGV[0], :port => ARGV[1].to_i}

      11      ]

      12  end

      13

      14  rc = RedisCluster.new(startup_nodes,32,:timeout => 0.1)

      15

      16  last = false

      17

      18  while not last

      19      begin

      20          last = rc.get("__last__")

      21          last = 0 if !last

      22      rescue => e

      23          puts "error #{e.to_s}"

      24          sleep 1

      25      end

      26  end

      27

      28  ((last.to_i+1)..1000000000).each{|x|

      29      begin

      30          rc.set("foo#{x}",x)

      31          puts rc.get("foo#{x}")

      32          rc.set("__last__",x)

      33      rescue => e

      34          puts "error #{e.to_s}"

      35      end

      36      sleep 0.1

      37  }

 

  程序作的事情很是简单: 它不断地以foo<number>为键,number为值,使用SET命令向数据库设置键值对:

    ·SET foo0 0

    ·SET foo1 1

    ·SET foo2 2

    ·And so forth

 

  代码中的每一个集群操做都使用一个beginrescue代码块(block)包裹着,由于咱们但愿在代码出错时,将错误打印到终端上面, 而不但愿应用由于异常(exception)而退出。

  代码的第七行是代码中第一个有趣的地方,它建立了一个Redis集群对象, 其中建立对象所使用的参数及其意义以下:第一个参数是记录了启动节点的startup_nodes列表, 列表中包含了两个集群节点的地址。第二个参数指定了对于集群中的各个不一样的节点, Redis 集群对象能够得到的最大链接数,第三个参数timeout指定了一个命令在执行多久以后,才会被看做是执行失败。

  启动列表中并不须要包含全部集群节点的地址,但这些地址中至少要有一个是有效的:一旦redis-rb-cluster成功链接上集群中的某个节点时,集群节点列表就会被自动更新, 任何真正的的集群客户端都应该这样作

  如今,程序建立的Redis集群对象实例被保存到rc变量里面,咱们能够将这个对象看成普通Redis对象实例来使用。

  在十一至十九行,咱们先尝试阅读计数器中的值,若是计数器不存在的话, 咱们才将计数器初始化为0:经过将计数值保存到Redis的计数器里面,咱们能够在示例重启以后,仍然继续以前的执行过程,而没必要每次重启以后都从foo0开始从新设置键值对。为了让程序在集群下线的状况下, 仍然不断地尝试读取计数器的值, 咱们将读取操做包含在了一个 while 循环里面, 通常的应用程序并不须要如此当心。

  二十一至三十行是程序的主循环,这个循环负责设置键值对,并在设置出错时打印错误信息。程序在主循环的末尾添加了一个sleep调用,让写操做的执行速度变慢,帮助执行示例的人更容易看清程序的输出。执行example.rb程序将产生如下输出:

  ruby ./example.rb

    1

    2

    3

    4

    5

    6

    7

    8

    9

    ^C (I stopped the program here)

  这个程序并非十分有趣, 稍后咱们就会看到一个更有趣的集群应用示例, 不过在此以前, 让咱们先使用这个示例来演示集群的从新分片操做。

 

集群从新分片

  现试试对集群进行从新分片操做。执行从新分片的过程当中,让example.rb程序处于运行状态,这样你就会看到,从新分片并不会对正在运行的集群程序产生任何影响,你也能够考虑将example.rb中的sleep调用删掉,从而让从新分片操做在近乎真实的写负载下执行;从新分片操做基本上就是将某些节点上的哈希槽移动到另一些节点上面,和建立集群同样,从新分片也可使用redis-trib程序来执行

 

  执行命令可开始一次从新分片操做:

    redis-trib.rb reshard 127.0.0.1:7000

  

  指定集群中一个节点地址便可,redis-trib”就会自动找到集群中其余节点

  目前redis-trib只能在管理员的协助下完成从新分片,要让redis-trib自动将哈希槽移动到另外一节点目前没法完成。另外,移动哈希槽目前只能以数量进行移动,不能以百分比进行移动,就是说指定redistrib移动50%哈希槽到另外一节点是不行的,必须指定数字

 

  此命令以问题的方式开启一次从新分片(reshard)。

  第一个问题,你想从新分片多少个哈希槽:

    >>> Performing Cluster Check (using node 127.0.0.1:7000)

    M: a466e88499423858c5f53de9be640500d9fb3e5b 127.0.0.1:7000

       slots:0-5460 (5461 slots) master

       1 additional replica(s)

    S: b36883be3b39692f71a441a67277ab23dff80afb 127.0.0.1:7004

       slots: (0 slots) slave

       replicates d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f

    M: d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f 127.0.0.1:7002

       slots:10923-16383 (5461 slots) master

       1 additional replica(s)

    S: 9b1d9c3e7bbcc955afce649f439cd2d094957313 127.0.0.1:7003

       slots: (0 slots) slave

       replicates 5055b631a9b310417fa75948a5e473e2e2e1cfee

    M: 5055b631a9b310417fa75948a5e473e2e2e1cfee 127.0.0.1:7001

       slots:5461-10922 (5462 slots) master

      1 additional replica(s)

    S: 406bda57ed591c2bd3b15955f687a57b03a653c0 127.0.0.1:7005

       slots: (0 slots) slave

       replicates a466e88499423858c5f53de9be640500d9fb3e5b

    [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)? 1000

 

    上面程序一直在运行,此时已经累计很多key了,尝试移动1000个哈希槽。

 

  此时出现第二个问题,接收这些哈希槽的节点ID是多少:

    What is the receiving node ID?a466e88499423858c5f53de9be640500d9fb3e5b

 

  接下来redis-trib”需知道要把这1000个哈希槽移动到哪一个节点,即哪一个目标节点负责接收这些哈希槽。此时我想移动到127.0.0.1:7000这个节点。指定节点要使用节点ID,且指定的节点必须是master节点信息已经打印在屏幕。也可经过如下命令找到指定节点ID

    redis-cli -p 7000 cluster nodes |grep 127.0.0.1:7000

    a466e88499423858c5f53de9be640500d9fb3e5b 127.0.0.1:7000@17000 myself,master - 0 1528103629000 1 connected 0-5460

 

    可看到目标节点为:a466e88499423858c5f53de9be640500d9fb3e5b

 

  接下来第三个问题,指定从哪些节点来移动keys到目标节点

    Please enter all the source node IDs.

      Type 'all' to use all the nodes as source nodes for the hash slots. #从其余每一个master上取一些哈希槽移动到目标节点,选择“all

      Type 'done' once you entered all the source nodes IDs. #指定要从哪些节点取哈希槽,输入各节点ID,以回车键分隔,完成后输入“done”指示节点指定完成

      Source node #1:d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f

      Source node #2:5055b631a9b310417fa75948a5e473e2e2e1cfee

      Source node #3:done

 

  接下来会列出要移动的哈希槽信息,而后提示是否执行从新分片计划:

    Do you want to proceed with the proposed reshard plan (yes/no)?yes

 

    确认后你将看到redis-trib移动的哈希槽的信息,移动的key也会打印出来。

 

  检查一下哈希槽分布状况(平均分布的时,三个master平均能分配到16384/3个哈希槽):

    redis-trib.rb check 127.0.0.1:7000

    >>> Performing Cluster Check (using node 127.0.0.1:7000)

    M: a466e88499423858c5f53de9be640500d9fb3e5b 127.0.0.1:7000

       slots:0-5961,10923-11421 (6461 slots) master

       1 additional replica(s)

    S: b36883be3b39692f71a441a67277ab23dff80afb 127.0.0.1:7004

       slots: (0 slots) slave

       replicates d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f

    S: 9b1d9c3e7bbcc955afce649f439cd2d094957313 127.0.0.1:7003

       slots: (0 slots) slave

       replicates 5055b631a9b310417fa75948a5e473e2e2e1cfee

    S: 406bda57ed591c2bd3b15955f687a57b03a653c0 127.0.0.1:7005

       slots: (0 slots) slave

       replicates a466e88499423858c5f53de9be640500d9fb3e5b

    M: d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f 127.0.0.1:7002

       slots:11422-16383 (4962 slots) master

       1 additional replica(s)

    M: 5055b631a9b310417fa75948a5e473e2e2e1cfee 127.0.0.1:7001

       slots:5962-10922 (4961 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.

 

  如何编写从新分片脚本?

  若是须要常常对集群执行从新分片,能够构建一些自动功能,但目前没法redis-trib自动从新平衡集群,检查整个集群节点上的key分布、智能地迁移哈希槽,该功能将在将来添加。

  reshard也可不用交互模式执行,如如下命令行:

    redis-trib.rb reshard --from <node-id> --to <node-id> --slots <number of slots> --yes <host>:<port>

 

一个更有趣的程序

  前面使用的示例程序example.rb它只是不断地对集群进行写入,并不检查写入结果是否正确。如集群可能错误地将example.rb发送的全部SET命令都改为了SET foo 42,但因为example.rb并不检查写入后的值,因此它不会意识到集群实际上写入的值是错误的。所以,redis-rb-cluster 项目包含了一个名为consistency-test.rb的示例应用,这个应用比起example.rb有趣得多:它建立了多个计数器(默认1000个),并经过发送INCR命令来增长这些计数器的值。

  在增长计数器值的同时,consistency-test.rb还执行如下操做:每次使用INCR命令更新一个计数器时,应用会记录下计数器执行INCR命令以后应该有的值。好比若是计数器的起始值为0,而此次是程序第50次向它发送INCR命令,那么计数器的值应该是50

  在每次发送INCR命令以前,程序会随机从集群中读取一个计数器的值,并将它与本身记录的值进行对比,看两个值是否相同。

  也就是说,这个程序是一个一致性检查器(consistency checker):若集群在执行INCR命令的过程当中,丢失了某条INCR命令,又或者多执行了某条客户端没有确认到的INCR命令,那么检查器将察觉到这一点:在前一种状况中,consistency-test.rb记录的计数器值将比集群记录的计数器值要大;而在后一种状况中,consistency-test.rb记录的计数器值将比集群记录的计数器值要小。

  运行consistency-test程序将产生相似如下的输出:

    $ ruby consistency-test.rb

    925 R (0 err) | 925 W (0 err) |

    5030 R (0 err) | 5030 W (0 err) |

    9261 R (0 err) | 9261 W (0 err) |

    13517 R (0 err) | 13517 W (0 err) |

    17780 R (0 err) | 17780 W (0 err) |

    22025 R (0 err) | 22025 W (0 err) |

    25818 R (0 err) | 25818 W (0 err) |

 

    结果展现了执行的读写和错误(因为系统不可用而没有接受的查询发生的错误)的数量.

  若程序察觉了不一致的状况出现,它将在输出行的末尾显式不一致的详细状况。好比,若是咱们在consistency-test.rb运行的过程当中,手动修改某个计数器的值:

    $ redis 127.0.0.1:7000> set key_217 0

    OK

 

    (in the other tab I see...)

 

    94774 R (0 err) | 94774 W (0 err) |

    98821 R (0 err) | 98821 W (0 err) |

    102886 R (0 err) | 102886 W (0 err) | 114 lost |

    107046 R (0 err) | 107046 W (0 err) | 114 lost |

    在咱们修改计数器值的时候,计数器的正确值是114(执行了114INCR命令),由于咱们将计数器的值设成了0, 因此consistency-test.rb会向咱们报告说丢失了114INCR命令。

  

  这个程序做为测试程序颇有意思,因此咱们用这个程序来测试故障恢复

 

  测试故障转移

  在执行本节操做的过程当中,请一直运行consistency-test程序。要触发一次故障转移,最简单的办法就是令集群中的某个master节点进入下线状态。首先用如下命令列出集群中的全部master节点:

    redis-cli -p 7000 cluster nodes | grep master

    3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385482984082 0 connected 5960-10921

    2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 master - 0 1385482983582 0 connected 11423-16383

    97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5959 10922-11422

  经过命令输出得知端口号为700070017002的节点都是master节点, 而后咱们能够经过向端口号7002master节点发送DEBUG SEGFAULT命令,让这个master节点崩溃:

    redis-cli -p 7002 debug segfault

    Error: Server closed the connection

  如今,切换到运行着consistency-test的标签页,能够看到consistency-test7002下线以后的一段时间里将产生大量的错误警告信息:

 

    18849 R (0 err) | 18849 W (0 err) |

    23151 R (0 err) | 23151 W (0 err) |

    27302 R (0 err) | 27302 W (0 err) |

 

    ... many error warnings here ...

 

    29659 R (578 err) | 29660 W (577 err) |

    33749 R (578 err) | 33750 W (577 err) |

    37918 R (578 err) | 37919 W (577 err) |

    42077 R (578 err) | 42078 W (577 err) |

  从consistency-test的这段输出能够看到,集群在执行故障转移期间,总共丢失了578个读命令和577个写命令,可是并无产生任何数据不一致。这听上去可能有点奇怪,由于在教程的开头咱们提到过Redis使用的是异步复制,在执行故障转移期间,集群可能会丢失写命令。可是在实际上,丢失命令的状况并不常见,由于Redis几乎是同时执行将命令回复发送给客户端,以及将命令复制给slave节点这两个操做,因此实际上形成命令丢失的时间窗口是很是小的。不过,尽管出现的概率不高,但丢失命令的状况仍是有可能会出现的,因此咱们对Redis集群不能提供强一致性的这一描述仍然是正确的。如今, 让咱们使用cluster nodes命令,查看集群在执行故障转移操做以后,主slave节点的布局状况:

 

  redis-cli -p 7000 cluster nodes

  3fc783611028b1707fd65345e763befb36454d73 127.0.0.1:7004 slave 3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 0 1385503418521 0 connected

  a211e242fc6b22a9427fed61285e85892fa04e08 127.0.0.1:7003 slave 97a3a64667477371c4479320d683e4c8db5858b1 0 1385503419023 0 connected

  97a3a64667477371c4479320d683e4c8db5858b1 :0 myself,master - 0 0 0 connected 0-5959 10922-11422

  3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7005 master - 0 1385503419023 3 connected 11423-16383

  3e3a6cb0d9a9a87168e266b0a0b24026c0aae3f0 127.0.0.1:7001 master - 0 1385503417005 0 connected 5960-10921

  2938205e12de373867bf38f1ca29d31d0ddb3e46 127.0.0.1:7002 slave 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 0 1385503418016 3 connected

 

  如今masters运行在 7000, 7001 7005端口上. 原来的master 7002如今变成了一个7005的一个slave节点.

 

  CLUSTER NODES命令的输出看起来有点复杂,其实他很是的简单,含义以下:

    ·节点ID

    ·IP:端口

    ·标志: master, slave, myself, fail,

    ·若是是个slave节点, 这里是它的master节点的NODE ID

    ·集群最近一次向节点发送 PING 命令以后, 过去了多长时间还没接到回复。.

    ·节点最近一次返回 PONG 回复的时间。

    ·节点的配置版本号(configuration epoch):详细信息请参考Redis集群规范 。

    ·本节点的网络链接状况:例如 connected

    ·节点目前包含的槽:例如 127.0.0.1:7001 目前包含号码为596010921的哈希槽

 

手动故障转移

  有时在master没有任何问题时强制故障转移是颇有必要的,如想升级masterRedis进程,通常会先故障转移,将其降级为slave再进行升级操做,以此下降对整个集群的影响。

 

  Redis集群使用“CLUSTER FAILOVER”来手动执行故障转移,该命令必须在要故障转移的master的一个slave上执行。

 

  相较于真实的master故障而后故障转移,手动故障转移是比较安全的,由于手动故障转移时客户端的切换是在确保新的master彻底复制了故障的旧的master数据的前提下发生的,因此避免了数据的丢失

 

  手动执行故障转移时,slave日志以下:

    # Manual failover user request accepted.

    # Received replication offset for paused master manual failover: 347540

    # All master replication stream processed, manual failover can start.

    # Start of election delayed for 0 milliseconds (rank #0, offset 347540).

    # Starting a failover election for epoch 7545.

    # Failover election won: I'm the new master.

 

  其基本过程如:客户端再也不链接旧的master,已经链接了的会被锁住,同时旧masterslave发送复制偏移量,slave获得偏移量后开始故障转移,而后新master通知旧master更新配置,成为新masterslave,此时还链接在旧master上的客户端解锁后会被重定向到新master

 

添加一个新节点

  基本过程是:添加一个空节点,而后移动一些数据给他。有两种状况:若新增的是master,从集群的其余节点中转移部分数据给它;若新增的是slave,则告诉它从一个已知的节点中同步复制集。

 

  添加master节点的状况

    1、添加一个空的redis实例节点,此处添加一个运行在端口7006的实例

    2、将空实例添加到现有集群中:

    redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000

 

        >>> Send CLUSTER MEET to node 127.0.0.1:7006 to make it join the cluster.

        [OK] New node added correctly.

 

        能够看到.使用addnode命令来添加节点,第一个参数是新节点的地址,第二个参数是任意一个已经存在的节点的IP和端口

        redis-trib脚本只是给发送“CLUSTER MEET”消息给节点,这也能够手动地经过客户端发送,但redis-trib在发送以前会检查集群的状态,因此,仍是用redis-trib脚原本操做集群会比较好。

  3、查看集群状态:

    redis-cli -c -p 7006 cluster nodes

    406bda57ed591c2bd3b15955f687a57b03a653c0 127.0.0.1:7005@17005 slave a466e88499423858c5f53de9be640500d9fb3e5b 0 1528264952479 7 connected

    bde6fc14465ecdbc71c6630edb5f9a3ab0c45cf0 127.0.0.1:7006@17006 myself,master - 0 1528264951000 0 connected

    5055b631a9b310417fa75948a5e473e2e2e1cfee 127.0.0.1:7001@17001 slave 9b1d9c3e7bbcc955afce649f439cd2d094957313 0 1528264951000 8 connected

    9b1d9c3e7bbcc955afce649f439cd2d094957313 127.0.0.1:7003@17003 master - 0 1528264950000 8 connected 5962-10922

    a466e88499423858c5f53de9be640500d9fb3e5b 127.0.0.1:7000@17000 master - 0 1528264951578 7 connected 0-5961 10923-11421

    b36883be3b39692f71a441a67277ab23dff80afb 127.0.0.1:7004@17004 slave d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f 0 1528264952078 3 connected

    d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f 127.0.0.1:7002@17002 master - 0 1528264951477 3 connected 11422-16383

 

    redis-trib.rb check 127.0.0.1:7006

    >>> Performing Cluster Check (using node 127.0.0.1:7006)

    M: bde6fc14465ecdbc71c6630edb5f9a3ab0c45cf0 127.0.0.1:7006

       slots: (0 slots) master

       0 additional replica(s)

    S: 406bda57ed591c2bd3b15955f687a57b03a653c0 127.0.0.1:7005

       slots: (0 slots) slave

       replicates a466e88499423858c5f53de9be640500d9fb3e5b

    S: 5055b631a9b310417fa75948a5e473e2e2e1cfee 127.0.0.1:7001

       slots: (0 slots) slave

       replicates 9b1d9c3e7bbcc955afce649f439cd2d094957313

    M: 9b1d9c3e7bbcc955afce649f439cd2d094957313 127.0.0.1:7003

       slots:5962-10922 (4961 slots) master

       1 additional replica(s)

    M: a466e88499423858c5f53de9be640500d9fb3e5b 127.0.0.1:7000

       slots:0-5961,10923-11421 (6461 slots) master

       1 additional replica(s)

    S: b36883be3b39692f71a441a67277ab23dff80afb 127.0.0.1:7004

       slots: (0 slots) slave

       replicates d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f

    M: d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f 127.0.0.1:7002

       slots:11422-16383 (4962 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.

 

    与其余master相比,新节点有两点区别:

    ·新节点未包含任何数据,由于哈希槽不是自动分配的,须要手工分配到新节点

    ·因为新节点还未包含哈希槽,当集群中某个slave想提成为master时,他不会参与选举过程

 

  4、从新分配哈希槽,而后检查哈希槽分布:

    redis-trib.rb reshard 127.0.0.1:7006

    redis-trib.rb check 127.0.0.1:7006

  

    >>> Performing Cluster Check (using node 127.0.0.1:7006)

    M: bde6fc14465ecdbc71c6630edb5f9a3ab0c45cf0 127.0.0.1:7006

       slots:0-1615,5962-7201,11422-12661 (4096 slots) master

       0 additional replica(s)

    S: 406bda57ed591c2bd3b15955f687a57b03a653c0 127.0.0.1:7005

      slots: (0 slots) slave

       replicates a466e88499423858c5f53de9be640500d9fb3e5b

    S: 5055b631a9b310417fa75948a5e473e2e2e1cfee 127.0.0.1:7001

       slots: (0 slots) slave

       replicates 9b1d9c3e7bbcc955afce649f439cd2d094957313

    M: 9b1d9c3e7bbcc955afce649f439cd2d094957313 127.0.0.1:7003

       slots:1616-1990,7202-10922 (4096 slots) master

       1 additional replica(s)

    M: a466e88499423858c5f53de9be640500d9fb3e5b 127.0.0.1:7000

       slots:2365-5961,10923-11421 (4096 slots) master

       1 additional replica(s)

    S: b36883be3b39692f71a441a67277ab23dff80afb 127.0.0.1:7004

       slots: (0 slots) slave

       replicates d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f

    M: d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f 127.0.0.1:7002

       slots:1991-2364,12662-16383 (4096 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.

 

  添加slave副本节点的状况

  添加一个slave副本节点有两种方法。

  无论使用哪一种方法都得先启动一个空Redis实例节点

 

  第一种方法:启动一个Redis空实例,后使用 redis-trib脚本的“--slave”选项

    redis-trib.rb add-node --slave 127.0.0.1:7007 127.0.0.1:7000

      第一个参数是新slave节点的地址;

      第二个参数是任意一个已经存在的节点的IP和端口,不须要指定此slave要添加为哪一个master副本节点,redis-trib会在拥有最少slave节点的master节点中随机选一个做为新增节点的master节点

 

      输出信息:

          ...

          Automatically selected master 127.0.0.1:7006

          >>> Send CLUSTER MEET to node 127.0.0.1:7007 to make it join the cluster.

          ...

          Configure node as replica of 127.0.0.1:7006.

          ...

 

    也能够直接指定新增slave节点的master节点:

    redis-trib.rb add-node --slave --master-id a466e88499423858c5f53de9be640500d9fb3e5b 127.0.0.1:7008 127.0.0.1:7003

 

    如此,便指定了新的slave节点是哪一个master节点的副本集。

 

  第二种方法启动一个Redis空实例,后将新节点以一个空master节点的形式加入到集群,而后再用“CLUSTER REPLICATE”将其转换为slave节点此方法也适用于给从slave节点更换master节点

  如,集群中master节点127.0.0.1:7002承载的哈希槽范围是1991-2364,12662-16383,节点IDd1ce7d9db6086c41f13ef0ce3753f82a3bfc420f

    1、将空实例添加到现有集群中:

      redis-trib.rb add-node 127.0.0.1:7009 127.0.0.1:7000

    二、链接空实例,执行复制进程:

      redis-cli -p 7009 CLUSTER REPLICATE d1ce7d9db6086c41f13ef0ce3753f82a3bfc

    三、认证信息:

      redis-cli -p 7000 cluster nodes |grep slave |grep d1ce7d9db6086c41f13ef0ce3753f82a3bfc

      b36883be3b39692f71a441a67277ab23dff80afb 127.0.0.1:7004@17004 slave d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f 0 1528271555000 11 connected

      5837a7c77a04b5100222dca1d226e4980764a97f 127.0.0.1:7009@17009 slave d1ce7d9db6086c41f13ef0ce3753f82a3bfc420f 0 1528271555500 11 connected

 

      可看到127.0.0.1:7004127.0.0.1:7009都是127.0.0.1:7002slave复制节点。

 

删除节点

  使用del-node”指令删除slave节点:

    redis-trib.rb del-node 127.0.0.1:7000 `<node-id>`

 

      第一个参数是任意一个节点的地址

      第二个节点是你想要移除的节点ID

 

  使用del-node”指令删除master节点:

    一、必须先将哈希槽所有迁移至别的master节点

    二、在使用del-node”指令删除master节点

 

  另外的一个方法是先将master故障转移降级为slave,且将另外的slave提高为master后再删除节点。显然,这样并无减小master节点数量,最终仍是只能先迁移哈希槽而后执行删除动做

 

Slave副本节点的迁移(Replicas migration

  Redis集群中给slaveslave节点更换master节点只需执行指令:

      CLUSTER REPLICATE <master-node-id>

 

  在特定场景下,无需管理员协助,自动将一个slave节点从当前master节点切换到另外一个master节点的自动从新配置过程叫副本迁移(Replicas migration

 

  注意;更多副本迁移的详细介绍在Redis集群规范中,此处只作简单介绍

 

  在某些状况下,将slave节点迁移到另外一个master节点下的缘由一般是the Redis Cluster is as resistant to failures as the number of replicas attached to a given master

 

  例如若是master节点和slave复制节点同时故障,那么一个master节点仅有一个slave复制节点的集群将不能再正常运行,由于没有其余Redis实例拥有故障masterslave节点所承载的哈希槽。虽然网络分区会形成一些节点被隔离,但其余状况也会致使集群故障,如硬件或者软件的故障致使节点宕机,此状况通常不会全部节点同时故障。再好比,集群中每一个master节点都有一个slave节点,凌晨4点时一个slave节点被kill掉,而后master节点在凌晨6点被kill掉,这样依然会致使集群不能工做。

 

  为提升系统可用性,可为每一个master添加额外的slave复制节点,但会增长成本。副本迁移功能能够只为部分master节点增长更多的slave复制节点。如集群中有10master节点,每一个有一个slave复制节点,共20个实例,而后能够将一些masterslave增长至3个。

  当集群中存在一个master节点有多个slave节点,但另外一个master节点没有slave节点时,复制集迁移功能会在master的多个slave节点中找一个节点,给没有slave节点的master节点作复制集。如当凌晨4点一个slave节点挂掉,另外一个slave节点将会代替它成为该master节点的slave节点,而后若是凌晨5master节点挂掉还能有一个slave节点能够升级为master,此时集群仍能够正常运行。

 

  所以副本迁移功能总结为:

    ·为了让副本迁移功能生效,须要在集群任意master节点上多添加几个slave节点

    ·在必要时,集群找到拥有最多slave节点的master,从其中挑选一个slave,进行副本迁移

    ·redis.conf中“cluster-migration-barrier”参数用于配置副本迁移。此参数保证Redis集群中不会出现裸奔的master节点,即保证每一个master节点都有slave节点。只有当一个master节点至少拥有给定数量个处于正常工做中的slave节点时,才会分配slave节点给集群中孤立的master节点。这个给定数量就是 cluster-migration-barrier。给定数量是1意味着一个slave节点只有在其master节点另外至少还有一个正常工做的slave节点的状况下才会被分配(副本迁移)。那些分配后仍然剩余migration barrierslave节点的master节点才会触发副本迁移,而不是分配前有migration barrierslave节点的master节点会触发节点分配!!

 

升级Redis集群中的节点版本

  升级slave节点版本

  只须要中止slave节点并使用新版本的Redis从新启动在相同端口便可。在节点关闭期间客户端链接过来会被重定向到另外可用的slave节点上。

 

  升级master节点版本

  相对复杂,建议的流程是:

    一、使用指令CLUSTER FAILOVER”手动触发故障转移,使master节点变成slave节点

    二、按照升级slave节点的方式升级该节点

    三、手动触发故障转移,让它变成新的master节点

 

  Redis数据迁移到Redis集群

  通常,数据迁移发生在两种状况下:

    ·原来的数据存在于一个Redis单实例

    ·原来的数据存在于一个分片环境中,数据存储在多个节点

 

  两种状况迁移都很方便,重要的细节是程序是否使用多键(multiple keys)操做,以及怎样使用多键操做。有如下三种状况:

    ·没有操做多个key(包括操做多个key的指令、事务、lua脚本)。全部key都独立操做

    ·操做了多个key(包括操做多个key的指令、事务、lua脚本),但这些key都有相同的哈希标签,好比这些被同时操做的keySUNION{user:1000}.foo {user:1000}.bar

    ·操做了多个key(包括操做多个key的指令、事务、lua脚本),这些key没有特别处理,也没有相同标签。

 

  第三种状况redis集群没法处理,需修改程序:不要使用多个key,或者给这些key加上相同的哈希标签,而后就能够迁移啦!

 

  前面两种状况能够直接作迁移,且迁移的流程同样。

  假设数据现被切割并保存在Nmaster节点存储(N=1时就是没有分片的状况),则须以如下步骤将数据迁移至Redis集群

    一、中止全部链接Redis集群的客户端程序。若是有自动在线迁移的方案,也许就不须要中止了。

    二、使用指令BGREWRITEAOF”让全部master节点产生AOF文件,等待文件建立完成

    三、修改AOF文件名称为aof-1, aof-2...aof-N以区别

    四、建立Nmaster节点,且开启实例的appendonly选项。Slave复制节点可晚些再添加

    五、中止新Redis集群全部节点,将前面保存的aof-1, aof-2...aof-Naof-1给第一个节点,aof-2给第二个节点,以此类推

    六、重启全部节点,可能会有警告提示说依据配置部分key不该当存储在此节点

    七、使用指令redis-trib.rb fix”让集群依据哈希槽自动迁移数据

    八、使用指令redis-trib.rb check”检查集群状态是否正常

    九、重启客户端程序,检测数据读写

 

  除此以外还可以使用指令redis-trib.rb import”从外部实例中导入数据到redis集群。该命令将源实例中的数据移动到目标Redis集群(该指令会把源实例中的数据都删除)。若源实例版本是Redis2.8,导入过程可能会比较长,由于2.8版本还未实现数据迁移的链接缓存,因此建议把源实例Redis版本先升级到3.x,再进行迁移。

相关文章
相关标签/搜索