# Redis Cluster配置教程
**简介**
Redis Cluster支持数据分片存储、主从复制、故障自动切换。
集群的搭建可以参考官方文档
https://redis.io/topics/cluster-tutorial

**Redis高可用集群的搭建**

**1. 安装redis环境**

首先需要准备3个以上的redis环境(建议6个以上),安装步骤如下:
```bash
wget http://download.redis.io/releases/redis-6.0.6.tar.gz
tar xzf redis-6.0.6.tar.gz
cd redis-6.0.6
make
```
在make编译的时候,可能会报错
```bash
‘struct redisServer’ has no member named ‘aof_state’
‘struct redisServer’ has no member named ‘aof_filename’
‘struct redisServer’ has no member named ‘rdb_filename’
‘struct redisServer’ has no member named ‘cluster_enabled’
............................................................
```
解决办法需要升级GCC
```bash
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
```
需要注意的是scl命令启用只是临时的,退出shell或重启就会恢复原系统gcc版本。
如果要长期使用gcc 9.3的话:
```bash
echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
```
这样退出shell重新打开就是新版的gcc了

**2. 修改redis配置**

分别在这几台redis机器上修改redis配置
首先查看redis一键启动脚本命令
```bash
cd /home/redis-6.0.6/utils
cat redis_init_script
```

可以看到下面几个配置

```bash
EXEC=/usr/local/bin/redis-server
CLIEXEC=/usr/local/bin/redis-cli

PIDFILE=/var/run/redis_${REDISPORT}.pid
CONF="/etc/redis/${REDISPORT}.conf"
```
其中EXEC和CLIEXEC的路径和我们的不一样,我们可以修改这个路径,
不过我这里为了统一,建立软连接来实现
```bash
ln -s /home/redis-6.0.6/src/redis-server /usr/local/bin/redis-server
ln -s /home/redis-6.0.6/src/redis-cli /usr/local/bin/redis-cli
```
接下来我们将redis_init_script这个启动脚本放到/etc/init.d/下并重命名
```bash
cp /home/redis-6.0.6/utils/redis_init_script /etc/init.d/redis_7001
vi /etc/init.d/redis_7001
REDISPORT=7001
ESC+:+wq
```
上面的启动脚本中我们可以看到pid和conf文件的路径,我们这里就使用这个路径吧

```bash
mkdir /etc/redis
mkdir /etc/redis/7001
mkdir /var/log/redis 

cp -p /home/redis-6.0.6/redis.conf /etc/redis/7001.conf

port 7001
cluster-enabled yes
cluster-config-file /etc/redis/node-7001.conf
cluster-node-timeout 5000
daemonize yes
pidfile /var/run/redis_7001.pid
dir /etc/redis/7001
logfile /var/log/redis/7001.log
bind 192.168.0.159
appendonly yes
```
同样创建7002和7003的配置
```bash
cd /etc/redis
mkdir 7002
mkdir 7003
cp 7001.conf 7002.conf
cp 7001.conf 7003.conf
#分别修改7002和7003的配置,将含有7001的分别变为7002和7003

cd /etc/init.d
cp redis_7001 redis_7002
cp redis_7001 redis_7003
#一样修改7002和7003的端口即可
```
分别启动
```bash
cd /etc/init.d/
./redis_7001 start
./redis_7002 start
./redis_7003 start
```
查看进程
```bash
ps -ef | grep redis
```

**3. 安装ruby环境**

```bash
yum -y install ruby
yum -y install rubygems
gem install redis
```
有可能在安装ruby的redis支持的时候回出问题,版本低了,解决办法

```bash
#https://rvm.io/
gpg2 --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
\curl -sSL https://get.rvm.io | bash -s stable
source /etc/profile.d/rvm.sh

#上面有可能连不上我们需要改下hosts
sudo vim /etc/hosts
199.232.28.133 raw.githubusercontent.com

rvm -v
rvm list known
rvm install 2.3
```

**4. redis集群设定**
```bash
cp /home/redis-6.0.6/src/redis-trib.rb /usr/local/bin/
#redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003
redis-trib.rb create --replicas 0 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003
#--replicas 每个master有几个slave
redis-trib.rb check

#redis6中取消了redis-trib.rb的支持
redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 --cluster-replicas 1

#Redis Cluster最低要求是3个主节点,如果需要集群需要认证,则在最后加入 -a pwssword 即可
#启动集群的时候如果报Bad directive or wrong number of arguments
#有可能是redis-cli版本没对,我们可以先进入/home/redis-6.0.6/src中调用
#启动集群前需要先启动每个redis服务
```
	
**5. 测试**
```bash
#这里一定要用-c参数
./redis-cli -c -p 7001
set name adtuu
#->Redirected to slot [5798] located at 127.0.0.1:7002
#OK
```

**6. 添加节点**
我们这里再添加三个节点,首先按照上面的配置启动三个redis服务,首先我们查看一下集群信息

```
cd /home/redis-6.0.6/src/
./redis-cli -c -p 7001
cluster info
cluster nodes
#redis-cli --cluster info 127.0.0.1:7001
```
可以看到我们已经有了三个master节点,接下来我们动态添加一个主节点

```
./redis-cli --cluster add-node 127.0.0.1:7004 127.0.0.1:7001
#7004是新的节点,7001是原来的已经存在的节点
#可以进入redis中查看节点状态
#cluster nodes
```
上面主节点已经添加好了,但是还需要给这个新的节点分配hash槽

```
#方法一、自动重新分配
./redis-cli --cluster rebalance --cluster-threshold 1 --cluster-use-empty-masters 127.0.0.1:7001
#方法二、手动分配
./redis-cli --cluster reshard 127.0.0.1:7001
```
再来试试添加从节点

```
#将7005设置为7001的从节点
./redis-cli --cluster add-node 127.0.0.1:7005 127.0.0.1:7001 --cluster-slave
#将7006设置为7004的从节点
./redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7004 --cluster-slave
```

**7. 故障测试与转移**
我们先看一下集群状态信息

```
127.0.0.1:7001> cluster nodes
679a0ea18c7f775299f62f3e422d2599e9db5f12 127.0.0.1:7006@17006 slave a7f59c4c1090f6202f82ff32285412a85735f9a8 0 1605663987000 4 connected
de13da639ba014d0ebbd3c266b9954cf108b7d20 127.0.0.1:7002@17002 master - 0 1605663988438 2 connected 6827-10922
4aca45f8803ebe8860222cac548592ddfc638536 127.0.0.1:7005@17005 slave fa7ed250047941d03beeda72b14ac093aaa91148 0 1605663987000 1 connected
a7f59c4c1090f6202f82ff32285412a85735f9a8 127.0.0.1:7004@17004 master - 0 1605663987928 4 connected 0-1364 5461-6826 10923-12287
1e7baa9b6bd9f091c7e9a6b4ea6907e1043e3427 127.0.0.1:7003@17003 master - 0 1605663987419 3 connected 12288-16383
fa7ed250047941d03beeda72b14ac093aaa91148 127.0.0.1:7001@17001 myself,master - 0 1605663988000 1 connected 1365-5460
```

```
#./redis-cli --cluster info 127.0.0.1:7001
127.0.0.1:7004 (a7f59c4c...) -> 1 keys | 4096 slots | 1 slaves.
127.0.0.1:7003 (1e7baa9b...) -> 0 keys | 4096 slots | 0 slaves.
127.0.0.1:7001 (fa7ed250...) -> 1 keys | 4096 slots | 1 slaves.
127.0.0.1:7002 (de13da63...) -> 0 keys | 4096 slots | 0 slaves.
```
7001和7004都有一个从节点,尝试将7004给关掉

```
./redis-cli -p 7004 debug segfault

127.0.0.1:7001 (fa7ed250...) -> 1 keys | 4096 slots | 1 slaves.
127.0.0.1:7006 (679a0ea1...) -> 1 keys | 4096 slots | 0 slaves.
127.0.0.1:7002 (de13da63...) -> 0 keys | 4096 slots | 0 slaves.
127.0.0.1:7003 (1e7baa9b...) -> 0 keys | 4096 slots | 0 slaves.
```
可以看到7004已经没有了,但是还是4个主节点,会将7004的从节点设定为主节点代替7004,重新启动7004,那么7004就变成了从节点。

**8. 删除节点**

```
./redis-cli --cluster del-node 127.0.0.1:7001 4aca45f8803ebe8860222cac548592ddfc638536
```

**9. 其他命令**

```
#重置节点数据
redis-cli -c -p 7001 -h xxxxxx
flushall
cluster reset soft

#之前将redis绑定在了127.0.0.1上导致外部不能
#先stop掉所有的redis服务
#删除/etc/redis/7001...7006下所有文件
#删除/etc/redis/node-*文件
redis-cli --cluster create 192.168.0.159:7001 192.168.0.159:7002 192.168.0.159:7003 192.168.0.159:7004 192.168.0.159:7005 192.168.0.159:7006 --cluster-replicas 1
```