# 028. 在项目中重新搭建一套读写分离+高可用+多 master 的 redis cluster 集群

上一章节对 redis cluster 最最基础的一些知识进行了了解。

redis cluster: master+slave 复制和读写分离/高可用和主备切换 都是自动支持的,支持多个 master 的 hash slot 支持数据分布式存储

所以停止之前所有的实例,包括 redis 主从和哨兵集群

# redis cluster 的重要配置

  • cluster-enabled <yes/no>

  • cluster-config-file <filename>

    这是指定一个文件,供 cluster 模式下的 redis 实例将集群状态保存在那里,包括集群中其他机器的信息,比如节点的上线和下限,故障转移,不是我们去维护的,给它指定一个文件,让 redis 自己去维护的

  • cluster-node-timeout <milliseconds>

    节点存活超时时长,超过一定时长,认为节点宕机,master 宕机的话就会触发主备切换,slave 宕机就不会提供服务

# 在三台机器上启动 6 个 redis 实例

redis cluster 集群要求至少 3 个 master,去组成一个高可用,健壮的分布式的集群,每个 master 都建议至少给一个 slave,3 个 master,3 个 slave,最少的要求

正式环境下,建议都是说在 6 台机器上去搭建,至少 3 台机器,保证每个 master 都跟自己的 slave 不在同一台机器上,如果是 6 台自然更好

3 台机器去搭建 6 个 redis 实例的 redis cluster

hostname 配置文件
eshop-cache01 7001.conf、 7002.conf
eshop-cache02 7003.conf、 7004.conf
eshop-cache03 7005.conf、 7006.conf

TIP

redis 还是一样的,只是配置文件中的属性不同了,建议使用默认的配置文件重新配置

配置目录整体概览

|- /etc
  |- /redis     # 存放配置文件,按端口名命名
    |- 7001.conf
  |- /redis-cluster  # 存放 redis 集群维护的配置文件目录
  |- /init.d  
    |-/redis_7001 # 启动脚本  
|- /var
  |-/log/redis  # 存放日志文件
    |-/7001.log # 日志文件
  |-/redis/7001 # 存放数据文件
1
2
3
4
5
6
7
8
9
10

配置文件和启动脚本

对于配置文件 主要要修改的在下面了

port 7001
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7001.conf
cluster-node-timeout 15000
daemonize	yes							
pidfile /var/run/redis_7001.pid 						
dir /var/redis/7001
logfile /var/log/redis/7001.log
# 如果后续不能正常创建集群,请把这里修改成 ip 的形式
bind eshop-cache01		
appendonly yes
1
2
3
4
5
6
7
8
9
10
11

为了方便快捷的把配置文件搞好。先执行以下命令

mkdir -p /etc/redis-cluster
mkdir -p /var/log/redis
mkdir -p /var/redis/7001

# 复制默认配置文件,并修改
cp /usr/local/redis-3.2.8/redis.conf /etc/redis/7001.conf
# 复制启动脚本,需要 6 个启动脚本 ,里面的 REDISPORT=7001 需要修改成和文件名对应的端口
cp /usr/local/redis-3.2.8/utils/redis_init_script /etc/init.d/redis_7001
1
2
3
4
5
6
7
8

然后下载 7001.conf 到 windows 中,按以上配置文件修改完成后, 复制其余 5 份出来,只要全局把 7001 替换成 其余 5 分节点的端口和 bind 修改好就可以了

启动 6 个 redis 实例

# 通过之前一样的命令启动 6 个实例
./redis_7001 start
# 查看日志是否启动正常,现在配置了日志文件的
cat /var/log/redis/7001.log
1
2
3
4

# 创建集群

之前启动的 6 个redis 实例只是单机的,需要使用工具创建集群

通过官网提供的工具 redis-trib.rb 工具创建,该工具依赖了 ruby,先装依赖

# 不要直接使用此命令安装,因为安装的是低版本的。参考本文后面的 Ruby 的安装
yum install -y ruby
# 不要使用 yum 安装,在 centos 6 中只会安装 1.8 版本的,并且连 ruby 也一起安装的
yum install -y rubygems
# 前面的安装请参考 本文后面的 Ruby 安装
gem install redis

## 让 redis-trib.rb 工具不在具体目录下也可以使用,和 windows path 效果类似
cp /usr/local/redis-3.2.8/src/redis-trib.rb /usr/local/bin

# 创建集群,注意这里需要使用 ip 地址,否则不成功
# --replicas: 每个 master 有几个 slave
# 6 台机器,3 个 master,3 个 slave,尽量自己让 master 和 slave 不在一台机器上
redis-trib.rb create --replicas 1 192.168.99.170:7001 192.168.99.170:7002 192.168.99.171:7003 192.168.99.171:7004 192.168.99.172:7005 192.168.99.172:7006

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

安装的话,不需要每台机器都安装,在 01 上安装和创建集群即可

# 在输入 yes 后,会如果报错。
Can I set the above configuration? (type 'yes' to accept): yes
/opt/rubies/ruby-2.3.8/lib/ruby/gems/2.3.0/gems/redis-4.1.0/lib/redis/client.rb:124:in `call': ERR Slot 0 is already busy (Redis::CommandError)

原因是 slot 被占用,解决方案如下,登录各个节点执行 cluster reset
[root@eshop-cache02 redis]# redis-cli -h 192.168.99.171 -p 7003
192.168.99.171:7003> cluster reset
OK
192.168.99.171:7003> exit
[root@eshop-cache02 redis]# redis-cli -h 192.168.99.171 -p 7004
192.168.99.171:7004> cluster reset
OK
192.168.99.171:7004> exit
[root@eshop-cache02 redis]# redis-cli -h 192.168.99.170 -p 7001
192.168.99.170:7001> cluster reset
OK
192.168.99.170:7001> exit
[root@eshop-cache02 redis]# redis-cli -h 192.168.99.170 -p 7002
192.168.99.170:7002> cluster reset
OK
192.168.99.170:7002> exit
[root@eshop-cache02 redis]# redis-cli -h 192.168.99.172 -p 7005
192.168.99.172:7005> cluster reset
OK
192.168.99.172:7005> exit
[root@eshop-cache02 redis]# redis-cli -h 192.168.99.172 -p 7006
192.168.99.172:7006> cluster reset
OK
192.168.99.172:7006> exit
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

再次创建集群后,终于成功了。从安装 ruby 开始到现在已经过去了 4 个小时, 真是太坎坷了

可以看到如下的日志,它选择了 3 个master,3 个 slave 并且都不在一台机器上

[root@eshop-cache01 redis]# redis-trib.rb create --replicas 1 192.168.99.170:7001 192.168.99.170:7002 192.168.99.171:7003 192.168.99.171:7004 192.168.99.172:7005 192.168.99.172:7006
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.99.170:7001
192.168.99.171:7003
192.168.99.172:7005
Adding replica 192.168.99.171:7004 to 192.168.99.170:7001
Adding replica 192.168.99.170:7002 to 192.168.99.171:7003
Adding replica 192.168.99.172:7006 to 192.168.99.172:7005
M: 3807711e01cd28509d7ba9839e601058bf2a30cf 192.168.99.170:7001
   slots:0-5460 (5461 slots) master
S: b0d66be3b15e117696c50a781ff24a842456733d 192.168.99.170:7002
   replicates 0ff0e8ab05a8b032aeacf24e0c7fea77be3f5c55
M: 0ff0e8ab05a8b032aeacf24e0c7fea77be3f5c55 192.168.99.171:7003
   slots:5461-10922 (5462 slots) master
S: a174fe6613862db8985f82caac58bde91dfbd664 192.168.99.171:7004
   replicates 3807711e01cd28509d7ba9839e601058bf2a30cf
M: cb2256b653cf5b7b3f9d1478cfa2953cc334c5bf 192.168.99.172:7005
   slots:10923-16383 (5461 slots) master
S: 9247dfb394441619da9da5b75b62b034c3f420e5 192.168.99.172:7006
   replicates cb2256b653cf5b7b3f9d1478cfa2953cc334c5bf
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join...
>>> Performing Cluster Check (using node 192.168.99.170:7001)
M: 3807711e01cd28509d7ba9839e601058bf2a30cf 192.168.99.170:7001
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: 9247dfb394441619da9da5b75b62b034c3f420e5 192.168.99.172:7006
   slots: (0 slots) slave
   replicates cb2256b653cf5b7b3f9d1478cfa2953cc334c5bf
M: cb2256b653cf5b7b3f9d1478cfa2953cc334c5bf 192.168.99.172:7005
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
S: a174fe6613862db8985f82caac58bde91dfbd664 192.168.99.171:7004
   slots: (0 slots) slave
   replicates 3807711e01cd28509d7ba9839e601058bf2a30cf
M: 0ff0e8ab05a8b032aeacf24e0c7fea77be3f5c55 192.168.99.171:7003
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: b0d66be3b15e117696c50a781ff24a842456733d 192.168.99.170:7002
   slots: (0 slots) slave
   replicates 0ff0e8ab05a8b032aeacf24e0c7fea77be3f5c55
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
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
41
42
43
44
45
46
47
48
49
50

可以通过 check 命令检查

[root@eshop-cache01 redis]# redis-trib.rb check eshop-cache01:7001
>>> Performing Cluster Check (using node eshop-cache01:7001)
M: 3807711e01cd28509d7ba9839e601058bf2a30cf eshop-cache01:7001
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: 9247dfb394441619da9da5b75b62b034c3f420e5 192.168.99.172:7006
   slots: (0 slots) slave
   replicates cb2256b653cf5b7b3f9d1478cfa2953cc334c5bf
M: cb2256b653cf5b7b3f9d1478cfa2953cc334c5bf 192.168.99.172:7005
   slots:10923-16383 (5461 slots) master
   1 additional replica(s)
S: a174fe6613862db8985f82caac58bde91dfbd664 192.168.99.171:7004
   slots: (0 slots) slave
   replicates 3807711e01cd28509d7ba9839e601058bf2a30cf
M: 0ff0e8ab05a8b032aeacf24e0c7fea77be3f5c55 192.168.99.171:7003
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
S: b0d66be3b15e117696c50a781ff24a842456733d 192.168.99.170:7002
   slots: (0 slots) slave
   replicates 0ff0e8ab05a8b032aeacf24e0c7fea77be3f5c55
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 读写分离+高可用+多 master

集群安装成功之后,就具有了如下功能:

  • 读写分离:每个 master 都有一个 slave
  • 高可用:master 宕机,slave 自动被切换过去
  • 多 master:横向扩容支持更大数据量

# Ruby 的安装

# Ruby 安装

在 ruby 官网找到一个安装任意版本的工具 ruby-install (opens new window)

cd /ust/local
# 安装 ruby-install
wget -O ruby-install-0.7.0.tar.gz https://github.com/postmodern/ruby-install/archive/v0.7.0.tar.gz
tar -xzvf ruby-install-0.7.0.tar.gz
cd ruby-install-0.7.0/
sudo make install

# 安装 2.3 版本 ruby,执行后会看到 update runby.. 应该是吧之前 1.8 版本的更新了
# 要等待好长时间,在安装过程中的时候 32% [305/947]  io.c ,947 的进度条。。
ruby-install ruby 2.3

# 如果你之前通过 yum 安装过 低版本的 ruby,那么需要移除掉
yum remove ruby
# 移除之后,发现提示有误
[root@eshop-cache01 ruby-2.3.8]# ruby -v
-bash: /usr/bin/ruby: No such file or directory
# 其实在 ruby-install ruby 2.3 安装完成过程中是有显示安装位置的
# 通过 ls 命令 连接到安装目录的 ruby 文件即可
ln -s /usr/local/src/ruby-2.3.8/ruby /usr/bin/ruby  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

以下尝试过好长时间都不能安装上,主要是 rvm 安装不了

解决 gem install redis redis requires Ruby version >= 2.2.2.报错问题 (opens new window)

或者参考 这篇文章 (opens new window)

# 安装 curl
sudo yum install curl
# 安装 RVM
# curl -L get.rvm.io | bash -s stable
# curl -L https://get.rvm.io | bash -s stable
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB

# 我再执行这步骤的时候老是报错 curl returned status '35'. ,下载不下来
# 按照官网的 https://rvm.io/ 方式也是报错
curl -sSL https://get.rvm.io | bash -s stable
source /usr/local/rvm/scripts/rvm

# 查看 rvm 库中已知的 ruby 版本
rvm list known
# 安装一个 ruby 版本
rvm install 2.3.3
# 使用一个 ruby 版本
rvm use 2.3.3
# 卸载一个已知版本
rvm remove 2.0.0
ruby --version

# 再安装redis就可以了
gem install 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

# rubygems 安装

安装方式请参考官网:https://rubygems.org/pages/download

cd /usr/local
wget https://rubygems.org/rubygems/rubygems-3.0.3.zip
# 如果没有安装 zip,请执行 yum install unzip
unzip rubygems-3.0.3.zip
cd rubygems-3.0.3
ruby setup.rb
ln -s /usr/local/rubygems-3.0.3/bin/gem /usr/bin/gem
1
2
3
4
5
6
7