搭建

第一步、安装必须依赖包

 

    yum install -y gcc automake autoconf libtool make gcc gcc-c++ zlib zlib-devel openssl openssl-devel pcre pcre-devel curl

 

第二步、创建集群目录

    mkdir -p  /usr/local/redis-cluster

    mkdir -p  /usr/local/redis-cluster/bin

    cd /usr/local/redis-cluster/

    mkdir -p 9001/data  9002/data  9003/data  9004/data  9005/data  9006/data

 

第三步、将已安装好的redis脚本拷贝值集群bin

    cd /usr/local/redis327/src/   (备注:以前安装的mysql目录)

    cp mkreleasehdr.sh redis-benchmark redis-check-aof redis-check-rdb  redis-cli redis-sentinel  redis-server redis-trib.rb /usr/local/redis-cluster/bin/

    cd /usr/local/redis-cluster/

    cp -rf  /usr/local/redis327/* 9001/

    cp -rf  /usr/local/redis327/* 9002/

    cp -rf  /usr/local/redis327/* 9003/

    cp -rf  /usr/local/redis327/* 9004/

    cp -rf  /usr/local/redis327/* 9005/

    cp -rf  /usr/local/redis327/* 9006/

 

第四步、准备redis.conf文件

    注意:每隔redis.conf文件对应自己的配置,如下9001配置,其他同理

    # 端口配置

    port 9001

    # 精灵进程

    daemonize yes

    # 关闭保护模式

    protected-mode no

    #requirepass qktz123$%^

    dir /usr/local/redis-cluster/9001/data/

    pidfile /var/run/redis_9001.pid

    cluster-enabled yes

    cluster-config-file nodes9001.conf

    cluster-node-timeout 15000

    appendonly yes

 

第五步、依次启动6个节点

    /usr/local/redis-cluster/bin/redis-server  /usr/local/redis-cluster/9001/redis.conf

    ...

    /usr/local/redis-cluster/bin/redis-server  /usr/local/redis-cluster/9006/redis.conf

   测试是否启动成功:

        /usr/local/redis-cluster/bin/redis-cli -h 10.30.0.31 -p 9001 -c

    如下图:

    

第六步、安装ruby环境

    yum install ruby

    yum install rubygems

    gem install redis  (注意:如果这步出错则按照下面解决问题)

   

 

    curl -L get.rvm.io | bash -s stable

    source  /usr/local/rvm/scripts/rvm

    rvm list known

    rvm install 2.3.4

    ruby -version

     注意:安装成功后需要再次执行gem install redis

 

第七步、创建集群

    /usr/local/redis-cluster/bin/redis-trib.rb create --replicas 1 10.30.0.31:9001 10.30.0.31:9002 10.30.0.31:9003 10.30.0.31:9004 10.30.0.31:9005 10.30.0.31:9006

     如下图:

     

      执行/usr/local/redis-cluster/bin/redis-cli -h 10.30.0.31 -p 9001 -c,此时集群创建成功

      

 

第七步、重启或者关闭集群

ps -ef | grep redis | awk '{print $2}' | kill -15

Redis客户端操作

1.1. 命令行工具redis-cli

官方提供的命令行客户端工具,在单机版redis基础上指定参数-c”即可。以下是在192.168.0.251上执行redis-cli的记录:

$ ./redis-cli -c -p 6379

127.0.0.1:6379> set foo bar

-> Redirected to slot [12182] located at 192.168.0.253:6379

OK

192.168.0.253:6379> set hello world

-> Redirected to slot [866] located at 192.168.0.251:6379

OK

192.168.0.251:6379> get foo

-> Redirected to slot [12182] located at 192.168.0.253:6379

"bar"

192.168.0.253:6379> get hello

-> Redirected to slot [866] located at 192.168.0.251:6379

"world"

 

查看集群中的节点:

192.168.0.251:6379> cluster nodes

1.2. 从slaves读数据

默认不能从slaves读取数据,但建立连接后,执行一次命令READONLY ,即可从slaves读取数据。如果想再次恢复不能从slaves读取数据,可以执行下命令READWRITE

1.3. jedisjava cluster client

官网:https://github.com/xetorthio/jedis

编程示例:

Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();

//Jedis Cluster will attempt to discover cluster nodes automatically

jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7379));

JedisCluster jc = new JedisCluster(jedisClusterNodes);

jc.set("foo", "bar");

String value = jc.get("foo");

1.4. r3cC++ cluster client

官网:https://github.com/eyjian/r3c

新增节点

2.1. 添加一个新主(master)节点

先以单机版配置和启动好redis-server,然后执行命令:

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

 

执行上面这条命令时,可能遇到错误“[ERR] Sorry, can't connect to node 127.0.0.1:7006”。引起该问题的原因可能是因为ruby的版本过低(运行ruby -v可以查看ruby的版本),可以尝试升级ruby再尝试,比如ruby 1.8.7版本就需要升级。对于Redis 3.0.5Redis 3.2.0,使用Ruby 2.3.1操作正常。请注意升级到最新版本的ruby也可能遇到这个错误。

 

另一个会引起这个问题的原因是从Redis 3.2.0版本开始引入了“保护模式(protected mode),防止redis-cli远程访问”,仅限redis-cli绑定到127.0.0.1才可以连接Redis server

为了完成添加新主节点,可以暂时性的关闭保护模式,使用redis-cli,不指定-h参数(但可以指定-p参数,或者-h参数值为127.0.0.1)进入操作界面:CONFIG SET protected-mode no

 

注意7006是新增的节点,而7000是已存在的节点(可为masterslave)。如果需要将7006变成某masterslave节点,执行命令:

cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e

 

新加入的master节点上没有任何数据(slots,运行redis命令cluster nodes可以看到这个情况)。当一个slave想成为master时,由于这个新的master节点不管理任何slots,它不参与选举。

可以使用工具redis-trib.rbresharding特性为这个新master节点分配slots,如:

redis-trib.rb reshard 127.0.0.1:7000,其中7000为集群中任意一个节点即可,redis-trib.rb将自动发现其它节点。

reshard过程中,将会询问reshard多少slots

How many slots do you want to move (from 1 to 16384)?,取值范围为1~16384,其中16384redis cluster的拥有的slots总数,比如想只移动100个,输入100即可。如果迁移的slots数量多,应当设置redis-trib.rb的超时参数--timeout值大一点。否则,迁移过程中易遇到超时错误[ERR] Calling MIGRATE: IOERR error or timeout reading to target instance”,导致只完成部分,可能会造成数据丢失。

接着,会提示“What is the receiving node ID?”,输入新加入的master节点ID。过程中如果遇到错误Sorry, can't connect to node 10.225.168.253:6380”,则可能需要暂时先关闭相应的保护模式。

 

如果在迁移过程遇到下面这样的错误:

>>> Check for open slots...

[WARNING] Node 192.168.0.3:6379 has slots in importing state (5461).

[WARNING] Node 192.168.0.5:6380 has slots in migrating state (5461).

[WARNING] The following slots are open: 5461

 

可以考虑使用命令“redis-trib.rb fix 192.168.0.3:6379”尝试修复。需要显示有节点处于migratingimporting状态,可以登录到相应的节点,使用命令cluster setslot 5461 stable”修改,参数5461为问题显示的slotID

2.2. 添加一个新从(slave)节点

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

 

注意这种方式,如果添加了多个slave节点,可能导致masterslaves不均衡,比如一些有3slave,其它只1slave。可以在slave节点上执行redis命令CLUSTER REPLICATE”进行调整,让它成为其它masterslaveCLUSTER REPLICATE”带一个参数,即master ID,注意使用redis-cli -c登录到slave上执行。

上面方法没有指定7006master,而是随机指定。下面方法可以明确指定为哪个masterslave

./redis-trib.rb add-node --slave --master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:7006 127.0.0.1:7000

 

删除节点

从集群中删除一个节点:

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

 

第一个参数为集群中任意一个节点,第二个参数为需要删除节点的ID

 

成功删除后,再调用下CLUSTER FORGET

CLUSTER FORGET <node-id>

 

注意如果是删除一个master节点,则需要先将它管理的slots的迁走,然后才可以删除它。

如果是masterslave机器不能连接,比如硬件故障导致无法启动,这个时候做不了del-node,只需要直接做CLUSTER 即可,在FORGET后,节点状态变成handshake

!!!请注意,需要在所有node上执行一次“CLUSTER FORGET”,否则可能遇到被剔除node的总是处于handshake状态。

master机器硬件故障

这种情况下,master机器可能无法启动,导致其上的master无法连接,master将一直处于master,fail”状态,如果是slave则处于slave,fail”状态。

如果是master,则会它的slave变成了master,因此只需要添加一个新的从节点作为原slave(已变成master)的slave节点。完成后,通过CLUSTER FORGET将故障的masterslave从集群中剔除即可。

!!!请注意,需要在所有node上执行一次“CLUSTER FORGET”,否则可能遇到被剔除node的总是处于handshake状态。

检查节点状态

redis-trib.rb check 127.0.0.1:6380

 

如发现如下这样的错误:

[WARNING] Node 192.168.0.11:6380 has slots in migrating state (5461).

[WARNING] The following slots are open: 5461

 

可以使用redis命令取消slots迁移(5461slotID):

cluster setslot 5461 stable

需要注意,须登录到192.168.0.11:6380上执行redissetslot子命令。

变更主从关系

使用命令cluster replicate,参数为master节点ID,注意不是IP和端口,在被迁移的slave上执行该命令。

slots相关命令

CLUSTER ADDSLOTS slot1 [slot2] ... [slotN]

CLUSTER DELSLOTS slot1 [slot2] ... [slotN]

CLUSTER SETSLOT slot NODE node

CLUSTER SETSLOT slot MIGRATING node

CLUSTER SETSLOT slot IMPORTING node

 

3.1. 迁移slosts

示例:将slot8从节点A迁移到节点B,有如下两种方法:

在节点B上执行:CLUSTER SETSLOT 8 IMPORTING A

在节点A上执行:CLUSTER SETSLOT 8 MIGRATING B

3.2. redis-trib.rb rebalance

当有增减节点时,可以使用命令:

redis-trib.rb rebalance 192.168.0.31:6379 --auto-weights

做一次均衡,简单点可以只指定两个参数:“192.168.0.31:6379”为集群中已知的任何一个节点,参数“-auto-weights”表示自动权重。

人工主备切换

在需要的slaves节点上执行命令:CLUSTER FAILOVER

查看集群信息

对应的redis命令为:cluster info,示例:

127.0.0.1:6381> cluster info

cluster_state:ok 所有slots正常则显示为OK,否则为error

cluster_slots_assigned:16384 多少slots被分配了,即多少被master管理了,16384为全部slots

cluster_slots_ok:16384 有多少slots是正常的

cluster_slots_pfail:0 有多少slots可能处于异常状态,处于这个状态并不表示有问题,仍能继续提供服务

cluster_slots_fail:0 有多少slots处于异常状态,需要修复才能服务

cluster_known_nodes:10 集群中的节点数

cluster_size:3 集群中master个数

cluster_current_epoch:11 本地的当前时间变量,用于故障切换时生成独一无二的增量版本号

cluster_my_epoch:0

cluster_stats_messages_sent:4049 通过集群消息总线发送的消息总数

cluster_stats_messages_received:4051 通过过集通过群消息总线收到的消息总数

禁止指定命令

KEYS命令很耗时,FLUSHDBFLUSHALL命令可能导致误删除数据,所以线上环境最好禁止使用,可以在Redis配置文件增加如下配置:

rename-command KEYS ""

rename-command FLUSHDB ""

rename-command FLUSHALL ""

 

常见故障

1[root@qkzhi-appzookeeper-1 bin]# ./redis-trib.rb create 10.30.0.31:9002

[ERR] Sorry, can't connect to node 10.30.0.31:9002

解决思路:

如果在升级ruby的前提下,出现这种问题,一般是redis配置了#masterauth "qktz123$%^"

#requirepass "qktz123$%^"后,需要进行如下修改:

vi /usr/local/rvm/gems/ruby-2.3.4/gems/redis-4.0.1/lib/redis/client.rb

 

如果不需要密码认证后,直接将password这一行删掉。

2如果最后一条日志为“16367:M 08 Jun 14:48:15.560 # Server started, Redis version 3.2.0”,节点状态始终终于fail状态,则可能是aof文件损坏了,这时可以使用工具edis-check-aof --fix进行修改,如:

../../bin/redis-check-aof --fix appendonly-6380.aof 

0x        a1492b9b: Expected prefix '

AOF analyzed: size=2705928192, ok_up_to=2705927067, diff=1125

This will shrink the AOF from 2705928192 bytes, with 1125 bytes, to 2705927067 bytes

Continue? [y/N]: y

3 in `call': ERR Slot 16011 is already busy (Redis::CommandError)

将所有节点上的配置项cluster-config-file指定的文件删除,然后重新启;或者在所有节点上执行下FLUSHALL命令。

另外,如果使用主机名而不是IP,也可能遇到这个错误,如:redis-trib.rb create --replicas 1 redis1:6379 redis2:6379 redis3:6379 redis4:6379 redis5:6379 redis6:6379”,可能也会得到错误“ERR Slot 16011 is already busy (Redis::CommandError)”。

4for lack of backlog (Slave request was: 51875158284)

默认值:

# redis-cli config get repl-timeout

A) "repl-timeout"

B) "10"

# redis-cli config get client-output-buffer-limit

A) "client-output-buffer-limit"

B) "normal 0 0 0 slave 268435456 67108864 60 pubsub 33554432 8388608 60"

 

增大:

redis-cli config set "client-output-buffer-limit" "normal 0 0 0 slave 2684354560 671088640 60 pubsub 33554432 8388608 60"

5 复制中断场景

A) masterslave缓冲区达到限制的硬或软限制大小,与参数client-output-buffer-limit相关;

B) 复制时间超过repl-timeout指定的值,与参数repl-timeout相关。

 

slave反复循环从master复制,如果调整以上参数仍然解决不了,可以尝试删除slave上的aofrdb文件,然后再重启进程复制,这个时候可能能正常完成复制。