Linux下搭建Redis集群
通过Redis的集群,可以实现多个Redis节点之间的数据共享,并且支持自动分割数据到不同的节点上。在集群过程中通过主从的分配可以提高Redis的可用性,不会因为某个节点宕掉或者不可达而导致整个集群网络的不可用。Redis 3.0版本后支持使用Redis-Cluster来搭建集群,因为Redis集群中至少应该有奇数个主节点(sentinel哨兵机制会对出现故障的主节点进行投票,超过半数才会主观点下线),所以我创建了6个Redis节点,其中3个为主节点,3个为从属节点,用于从主节点拉取数据进行备份。
- 由于资源有限,所以只使用一台机器做这个实验,在这台机器上开启六个Redis服务(不同的端口)
- 机器的IP:10.167.201.57
- 7000,7002,7004端口全部为主
- 7001,7003,7005端口全部为从
- redis版本:4.0.1
- 机器的防火墙都是关闭的
redis的安装
可以看前面写的这篇文章:Redis安装
集群搭建
编译安装后,在Reids的src目录下有个redis-trib.rb文件,将其复制到/usr/bin/目录下,方便后期搭建集群使用,这个文件使用ruby语言写的。
cp /usr/local/redis-stable/src/redis-trib.rb /usr/bin
创建节点,在redis目录下创建一个cluster目录:
mkdir cluster
然后在该目录下创建六个目录,分别命名为7000、7001、7002、7003、7004和7005:
cd cluster/
mkdir 7000 7001 7002 7003 7004 7005
在7000目录下创建一个Redis配置文件redis.conf,内容如下:
port 7000
bind 10.167.201.57
daemonize yes
pidfile /var/run/redis_7000.pid
cluster-enabled yes
cluster-config-file nodes_7000.conf
cluster-node-timeout 15000
appendonly yes
上述配置是开启Redis集群的最简配置,各项配置的含义如下:
- port 7000:Redis节点的端口号为7000;
- bind 10.167.201.57:绑定本机的IP地址;
- daemonize yes:以后台服务的形式开启Redis;
- pidfile /var/run/redis_7000.pid:以该配置启动Redis后将在/var/run/目录下创建一个redis_port.pid文件;
- cluster-enabled yes:是否开启集群,yes;
- cluster-config-file nodes_7000.conf:集群配置文件,启动后自动生成,文件名称为nodes_7000.conf。该文件将保持集群配置信息,以保证重启该Redis节点后能够保持集群状态;
- cluster-node-timeout 15000:请求超时时间,默认为15秒;
- appendonly yes:是否开启aof日志,开启后每次写操作都记录一条日志。
剩下的70017005的配置文件除了端口号改为相应的外,其他配置保持一致。配置好70007005端口的Redis配置文件后,进入/redis/bin目录启动这些节点:
./redis-server cluster/7000/redis.conf
./redis-server cluster/7001/redis.conf
./redis-server cluster/7002/redis.conf
./redis-server cluster/7003/redis.conf
./redis-server cluster/7004/redis.conf
./redis-server cluster/7005/redis.conf
查看是否启动成功:
ps -ef | grep redis
现在我们已经有6个正在运行中的Redis实例,接下来需要使用这些实例来创建集群。接着使用redis-trib.rb创建集群,该文件使用ruby编写,所以使用redis-trib.rb之前得先安装ruby。
安装ruby
- wget httpss://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
- tar -xvf ruby-2.3.1.tar.gz
- cd ruby-2.3.1
- ./configure -prefix=/usr/local/ruby
- make && make install
ruby -v,查看是否安装成功。若提示command not found,则需要在profile中加入环境变量。
- vim /etc/profile
- export RUBY_HOME=/usr/local/ruby
- export PATH=$RUBY_HOME/bin:$PATH
最后执行 source /etc/profile,使配置生效。
安装完ruby以后,再安装与redis相关的插件:
gem install redis
最后,输入以下命令开启集群:
redis-trib.rb create --replicas 1 10.167.201.57:7000 10.167.201.57:7001 10.167.201.57:7002 10.167.201.57:7003 10.167.201.57:7004 10.167.201.57:7005
选项--replicas 1表示我们希望为集群中的每个主节点创建一个从节点,之后跟着的其他参数则是这个集群实例的地址列表:3个主节点(Master,即70007002)3个从节点(Slave,即70037005)。输入该命令后,终端打印出如下配置:
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
10.167.201.57:7000
10.167.201.57:7001
10.167.201.57:7002
Adding replica 10.167.201.57:7005 to 10.167.201.57:7002
Adding replica 10.167.201.57:7004 to 10.167.201.57:7001
Adding replica 10.167.201.57:7003 to 10.167.201.57:7000
M: 6c388e0cd04990b23e2e65b285b5f9c1bc996538 10.167.201.57:7000
slots:0-5460 (5461 slots) master
M: 01e9cd67978b1cad73a40e9a70000a236744cb17 10.167.201.57:7001
slots:5461-10922 (5462 slots) master
M: 72a649017fdd5d4045f9d58df8b231c2d69e6c32 10.167.201.57:7002
slots:10923-16383 (5461 slots) master
S: b90aa487cf48270df43e79af98807bb5ffabbe34 10.167.201.57:7003
replicates 6c388e0cd04990b23e2e65b285b5f9c1bc996538
S: f873f54c61dbb613df58fa4b9ff8bc3dd48e2388 10.167.201.57:7004
replicates 01e9cd67978b1cad73a40e9a70000a236744cb17
S: daa813e169580417f4410fac86a3d4ab9abda804 10.167.201.57:7005
replicates 72a649017fdd5d4045f9d58df8b231c2d69e6c32
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 10.167.201.57:7000)
M: 6c388e0cd04990b23e2e65b285b5f9c1bc996538 10.167.201.57:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: b90aa487cf48270df43e79af98807bb5ffabbe34 10.167.201.57:7004
slots: (0 slots) slave
replicates 6c388e0cd04990b23e2e65b285b5f9c1bc996538
M: 72a649017fdd5d4045f9d58df8b231c2d69e6c32 10.167.201.57:7001
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: 01e9cd67978b1cad73a40e9a70000a236744cb17 10.167.201.57:7002
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: daa813e169580417f4410fac86a3d4ab9abda804 10.167.201.57:7005
slots: (0 slots) slave
replicates 72a649017fdd5d4045f9d58df8b231c2d69e6c32
S: f873f54c61dbb613df58fa4b9ff8bc3dd48e2388 10.167.201.57:7003
slots: (0 slots) slave
replicates 01e9cd67978b1cad73a40e9a70000a236744cb17
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
其中M开头的节点为主节点,S开头的为从节点。从从节点的replicates(复制的意思)信息可以看出7000的从节点为7004,7001的从节点为7005,7002的从节点为7003。7000节点的拥有5461个哈希槽(0 - 6460 slots),7001节点拥有5462个哈希槽(5461 - 10922 slots),7002节点拥有5461个哈希槽(10923 - 16383 slots),而从属节点并没有分配哈希槽。从最后一行的输出信息可以看出,Redis集群总共有16384个哈希槽(slots)。此外,那些一大串的字符称为节点ID。
集群测试
通过上面的集群配置,以上6个redis节点的结构可以通过下图展示:
颜色深的节点为颜色浅的节点的主节点,所有节点彼此之间互联(ping-pong)。下面对这些集群节点进行一些测试。
测试存取
[root@localhost ~]# redis-cli -c -h 10.167.201.57 -p 7000 # 加上-c选项表示以集群的方式登录
10.167.201.57:7000> set key1 123
-> Redirected to slot [9189] located at 10.167.201.57:7003 # 可以看到,这个key1被重定向到了10.167.201.57:7003这台redis机器上
OK
10.167.201.57:7003> set key2 abc
-> Redirected to slot [4998] located at 10.167.201.57:7000
OK
10.167.201.57:7000> set key3 test # 没有重定向提示信息的就表示存储到了本地上
OK
10.167.201.57:7000>
如果不加-c的话,只会登录目标机器,操作的也只是目标机器,而不会像集群那样重定向数据。任意一个节点都可以创建key,或者查看key。
测试主从切换
在集群过程中可以通过主从的分配来提高Redis的可用性。比如这个例子,集群有7000、7001和7002 3个主节点,如果这3个节点都没有从节点,假设7001宕机了,那么整个集群就会因为缺少5501-11000这个范围的哈希槽而变得不可用。所以我们在集群建立的时候,一定要为每个主节点都添加了从节点, 比如像上面的例子那样,集群包含主节点7000、7001和7002以及从节点7003、7004和7005, 那么即使7001宕系统也可以继续正常工作。当7001这个主节点宕机后,Redis集群将会选择7001的从节点7004作为新的主节点以确保集群正常的工作。当重新启动7001后,其自动变为了7004的从节点,角色完成了转换。为了验证这个理论,下面将7001节点杀死,然后观察:
现在重新启动7001节点,然后观察:
但假如7005和7001同时宕机,那么集群将不可用。
操作集群
检测集群状态
[root@center-cluster1 ~]# redis-trib.rb check 10.167.201.57:7000
>>> Performing Cluster Check (using node 10.167.201.57:7000)
M: ba6726fc4f1a63f982d322e7e293983466c31b22 10.167.201.57:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 1f5ad1183c56c598b3b5c3b350d54a7629d8dab8 10.167.201.57:7005
slots: (0 slots) slave
replicates 55923487878aeff5da7c1d9e7df18629aaa5b0f0
M: 55923487878aeff5da7c1d9e7df18629aaa5b0f0 10.167.201.57:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 8ba3f6e7400ff1589fd3b810f9583210fe69be26 10.167.201.57:7003
slots: (0 slots) slave
replicates ba6726fc4f1a63f982d322e7e293983466c31b22
S: b222b06609b2a9172ea34b9b72e56d324371128a 10.167.201.57:7004
slots: (0 slots) slave
replicates 56136f718ab3a328a5bf68c4a12701d3f1edbec2
M: 56136f718ab3a328a5bf68c4a12701d3f1edbec2 10.167.201.57:7001
slots:5461-10922 (5462 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.
[root@center-cluster1 ~]#
列出所有节点信息
10.167.201.57:7000> cluster nodes
1f5ad1183c56c598b3b5c3b350d54a7629d8dab8 10.167.201.57:7005@17005 slave 55923487878aeff5da7c1d9e7df18629aaa5b0f0 0 1536907557000 6 connected
55923487878aeff5da7c1d9e7df18629aaa5b0f0 10.167.201.57:7002@17002 master - 0 1536907557000 3 connected 10923-16383
8ba3f6e7400ff1589fd3b810f9583210fe69be26 10.167.201.57:7003@17003 slave ba6726fc4f1a63f982d322e7e293983466c31b22 0 1536907558364 4 connected
ba6726fc4f1a63f982d322e7e293983466c31b22 10.167.201.57:7000@17000 myself,master - 0 1536907558000 1 connected 0-5460
b222b06609b2a9172ea34b9b72e56d324371128a 10.167.201.57:7004@17004 slave 56136f718ab3a328a5bf68c4a12701d3f1edbec2 0 1536907557360 5 connected
56136f718ab3a328a5bf68c4a12701d3f1edbec2 10.167.201.57:7001@17001 master - 0 1536907559365 2 connected 5461-10922
10.167.201.57:7000>
查看集群信息
cluster info
增加节点
cluster meet ip port 命令可以添加节点,例如现在在B机器上新增加了一个redis服务,端口为7006,现在要把这个新增的redis服务加入到集群节点中来:
10.167.201.57:7000> cluster meet 192.168.77.128 7006
OK
10.167.201.57:7000> cluster nodes
deca81cf98ac8206419096f8b86a7a6e925078ad 10.167.201.57:7006@17006 master - 0 1515075895000 0 connected
.....以下省略......
可以看到7006成功添加到了节点中,身份是master。
使用以上方式添加的节点,都会是master身份,而 cluster replicate node_id(node_id为主节点的id号)命令可以将当前节点设置为指定节点的从(slave):
[root@localhost ~]# redis-cli -c -h 10.167.201.57-p 7006
10.167.201.57:7006> cluster replicate ef2f571de1d8d1bfa5d96acab297ad857c09d33c
OK
10.167.201.57:7006> CLUSTER NODES
.....以上省略......
deca81cf98ac8206419096f8b86a7a6e925078ad 10.167.201.57:7006@17006 myself,slave ef2f571de1d8d1bfa5d96acab297ad857c09d33c 0 1515047943000 0 connected
10.167.201.57:7006>
可以看到成功把7006指定为 ef2f571de1d8d1bfa5d96acab297ad857c09d33c 这个节点的slave,这个节点对应的端口是7001。
删除节点
cluster forget node_id 命令可以移除某个节点,例如把7006移除掉:
[root@localhost ~]# redis-cli -c -h 10.167.201.57-p 7001
10.167.201.57:7001> cluster forget deca81cf98ac8206419096f8b86a7a6e925078ad
OK
10.167.201.57:7001>
这个命令不能移除master身份的节点,而且当前登录的节点(myself)也不能移除,只能移除非当前登录的slave节点。如果想要移除master节点,只能先把这个master指定为slave之后再移除。
保存操作
cluster saveconfig命令可以把当前集群的操作保存到配置文件里:
10.167.201.57:7001> CLUSTER SAVECONFIG
OK
10.167.201.57:7001> quit
[root@localhost ~]# cat /data/redis_data/7001/nodes_7001.conf
d75dd3c61389200941c6987062a79ba8db576741 10.167.201.57:7005@17005 slave ef2f571de1d8d1bfa5d96acab297ad857c09d33c 0 1515076783944 2 connected
c9cef49da3e8acbc47d9b3151b04589e349031b1 10.167.201.57:7003@17003 master - 0 1515076785957 4 connected 5461-10922
03fc051e6ba17eee1efa6188e961455958b154e0 10.167.201.57:7000@17000 master - 0 1515076784951 1 connected 0-5460
deca81cf98ac8206419096f8b86a7a6e925078ad 10.167.201.57:7006@17006 slave ef2f571de1d8d1bfa5d96acab297ad857c09d33c 0 1515076785153 2 connected
e95229afb8b6f22ff4414aaf1173574e39a12526 10.167.201.57:7002@17002 slave c9cef49da3e8acbc47d9b3151b04589e349031b1 0 1515076787970 4 connected
ef2f571de1d8d1bfa5d96acab297ad857c09d33c 10.167.201.57:7001@17001 myself,master - 0 1515076786000 2 connected 10923-16383
824b56352f1b464918702aba2597e9bf46eb70dc 10.167.201.57:7004@17004 slave 03fc051e6ba17eee1efa6188e961455958b154e0 0 1515076786964 5 connected
vars currentEpoch 6 lastVoteEpoch 0
[root@localhost ~]#