Redis Cluster

转 https://www.cnblogs.com/wxd0108/p/5798498.htmlphp

 

前言

redis 是咱们目前大规模使用的缓存中间件,因为它强大高效而又便捷的功能,获得了普遍的使用。如今的2.x的稳定版本是2.8.19,也是咱们项目中广泛用到的版本。css

redis在年初发布了3.0.0,官方支持了redis cluster,也就是集群。至此结束了redis 没有官方集群的时代,以前咱们用redis cluster用的最多的应该是twitter 发布的Twemproxy(https://github.com/twitter/twemproxy)html

还有就是豌豆荚开发的codis (https://github.com/wandoulabs/codis)node

这2个我会在后续去使用它们。下面的文字,我尽可能用通熟易懂的方式来阐述。ios

 

redis cluster 理论知识

截止写这篇文章前,redis 3.x的最新版本是3.0.5。今天的学习和实践就是用这个版本。git

 

Redis Cluster设计要点

redis cluster在设计的时候,就考虑到了去中心化,去中间件,也就是说,集群中的每一个节点都是平等的关系,都是对等的,每一个节点都保存各自的数据和整个集群的状态。每一个节点都和其余全部节点链接,并且这些链接保持活跃,这样就保证了咱们只须要链接集群中的任意一个节点,就能够获取到其余节点的数据。github

那么redis 是如何合理分配这些节点和数据的呢?web

Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另一种叫作哈希槽 (hash slot)的方式来分配的。redis cluster 默认分配了 16384 个slot,当咱们set一个key 时,会用CRC16算法来取模获得所属的slot,而后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384redis

注意的是:必需要3个之后的主节点,不然在建立集群时会失败,咱们在后续会实践到。算法

因此,咱们假设如今有3个节点已经组成了集群,分别是:A, B, C 三个节点,它们能够是一台机器上的三个端口,也能够是三台不一样的服务器。那么,采用哈希槽 (hash slot)的方式来分配16384个slot 的话,它们三个节点分别承担的slot 区间是:

  • 节点A覆盖0-5460;
  • 节点B覆盖5461-10922;
  • 节点C覆盖10923-16383.

以下图所示:

这里写图片描述

那么,如今我想设置一个key ,好比叫my_name:

set my_name yangyi

按照redis cluster的哈希槽算法:CRC16('my_name')%16384 = 2412。 那么就会把这个key 的存储分配到 A 上了。

一样,当我链接(A,B,C)任何一个节点想获取my_name这个key时,也会这样的算法,而后内部跳转到B节点上获取数据。

这种哈希槽的分配方式有好也有坏,好处就是很清晰,好比我想新增一个节点D,redis cluster的这种作法是从各个节点的前面各拿取一部分slot到D上,我会在接下来的实践中实验。大体就会变成这样:

  • 节点A覆盖1365-5460
  • 节点B覆盖6827-10922
  • 节点C覆盖12288-16383
  • 节点D覆盖0-1364,5461-6826,10923-12287

一样删除一个节点也是相似,移动完成后就能够删除这个节点了。

因此redis cluster 就是这样的一个形状:

这里写图片描述

 

Redis Cluster主从模式

redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。

上面那个例子里, 集群有ABC三个主节点, 若是这3个节点都没有加入从节点,若是B挂掉了,咱们就没法访问整个集群了。A和C的slot也没法访问。

因此咱们在集群创建的时候,必定要为每一个主节点都添加了从节点, 好比像这样, 集群包含主节点A、B、C, 以及从节点A一、B一、C1, 那么即便B挂掉系统也能够继续正确工做。

B1节点替代了B节点,因此Redis集群将会选择B1节点做为新的主节点,集群将会继续正确地提供服务。 当B从新开启后,它就会变成B1的从节点。

不过须要注意,若是节点B和B1同时挂了,Redis集群就没法继续正确地提供服务了。

流程下图所示:

这里写图片描述

 

redis cluster 动手实践

网上有不少教程,我最早是按照这个教程(http://blog.51yip.com/nosql/1725.html) 一步步的按照这个教程来,但是在最后启动集群的时候第一台机器的6379端口死活启动不了,这样就没有3台主服务器,就完成不了集群。最后也没找到解决办法。[知道缘由了:我把redis-trib.rb create --replicas 1的 这个1没有写!!!!]

如今,仍是按照官方的教程,全程再演示一次,官方教程是在一台机器上启动6个节点,3个当主,3个当从(http://redis.io/topics/cluster-tutorial):

先下载官方的redis 版本(3.0.5) : http://download.redis.io/releases/redis-3.0.5.tar.gz

下载不了,请自行FQ。我此次是在centos6.5上演示,用的是root 帐户。

若是以前已经下载了redis的 2.x版本,只须要将 /usr/local/bin/redis-* 这几个命令先删除便可。

 

1.解压

[root@web3 ~]# tar zxvf redis-3.0.5.tar.gz

2.安装

[root@web3 ~]# cd redis-3.0.5
[root@web3 ~]# make && make install 

3.将redis-trib.rb 复制到/usr/local/bin

[root@web3 redis-3.0.5]# cd src/
[root@web3 src]# cp redis-trib.rb /usr/local/bin

4.开始集群搭建

复制代码
[root@web3 redis-3.0.5]# vi redis.conf
#修改如下地方
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
复制代码

 

 
新建6个节点:
 
复制代码
[root@web3 redis-3.0.5]# mkdir -p /usr/local/cluster-test
[root@web3 redis-3.0.5]# cd /usr/local/cluster-test/
[root@web3 cluster-test]# mkdir 7000
[root@web3 cluster-test]# mkdir 7001
[root@web3 cluster-test]# mkdir 7002
[root@web3 cluster-test]# mkdir 7003
[root@web3 cluster-test]# mkdir 7004
[root@web3 cluster-test]# mkdir 7005
复制代码

将redis.conf 分别拷贝到这6个文件夹中,并修改为对应的端口号

 
复制代码
#拷贝配置文件
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7000
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7001
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7002
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7003
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7004
[root@web3 cluster-test]# cp /root/redis-3.0.5/redis.conf /usr/local/cluster-test/7005
#修改端口号
root@web3 cluster-test]# sed -i "s/7000/7001/g" /usr/local/cluster-test/7001/redis.conf
[root@web3 cluster-test]# sed -i "s/7000/7002/g" /usr/local/cluster-test/7002/redis.conf
[root@web3 cluster-test]# sed -i "s/7000/7003/g" /usr/local/cluster-test/7003/redis.conf
[root@web3 cluster-test]# sed -i "s/7000/7004/g" /usr/local/cluster-test/7004/redis.conf
[root@web3 cluster-test]# sed -i "s/7000/7005/g" /usr/local/cluster-test/7005/redis.conf
复制代码

分别,启动这6个节点

复制代码
[root@web3 cluster-test]# cd /usr/local/cluster-test/7000/
[root@web3 7000]# redis-server redis.conf
[root@web3 7000]# cd ../7001
[root@web3 7001]# redis-server redis.conf
[root@web3 7001]# cd ../7002
[root@web3 7002]# redis-server redis.conf
[root@web3 7002]# cd ../7003
[root@web3 7003]# redis-server redis.conf
[root@web3 7003]# cd ../7004
[root@web3 7004]# redis-server redis.conf
[root@web3 7004]# cd ../7005
[root@web3 7005]# redis-server redis.conf
[root@web3 7005]#
复制代码

查看6个节点的启动进程状况:

 
复制代码
[root@web3 7005]# ps -ef|grep redis
root 11380 1 0 07:37 ? 00:00:00 redis-server *:7000 [cluster]
root 11384 1 0 07:37 ? 00:00:00 redis-server *:7001 [cluster]
root 11388 1 0 07:37 ? 00:00:00 redis-server *:7002 [cluster]
root 11392 1 0 07:37 ? 00:00:00 redis-server *:7003 [cluster]
root 11396 1 0 07:37 ? 00:00:00 redis-server *:7004 [cluster]
root 11400 1 0 07:37 ? 00:00:00 redis-server *:7005 [cluster]
root 11404 8259 0 07:38 pts/0 00:00:00 grep redis
复制代码

将6个节点连在一块儿构招成集群

须要用到的命令就是redis-trib.rb,这是官方的一个用ruby写的一个操做redis cluster的命令,因此,你的机器上须要安装ruby。咱们先试一下这个命令:

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

由于咱们要新建集群, 因此这里使用create命令. --replicas 1 参数表示为每一个主节点建立一个从节点. 其余参数是实例的地址集合。

因为我机子上没安装ruby,因此,会报错:

/usr/bin/env: ruby: No such file or directory

那先安装ruby和rubygems: 

[root@web3 7005]# yum install ruby ruby-devel rubygems rpm-build

而后,再执行一次,发现仍是报错:

[root@web3 7005]# 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
/usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- redis (LoadError)
from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /usr/local/bin/redis-trib.rb:25
[root@web3 7005]#
 原来是ruby和redis的链接没安装好:
 
[root@web3 7005]# gem install redis
Successfully installed redis-3.2.1
1 gem installed
Installing ri documentation for redis-3.2.1...
Installing RDoc documentation for redis-3.2.1...

好了。最重要的时刻来临了,胜败成举在此了,啊啊啊啊啊啊,好激动:

 
复制代码
[root@web3 7005]# 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
>>> Creating cluster
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:7000
127.0.0.1:7001
127.0.0.1:7002
Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
M: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
S: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
replicates 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
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 127.0.0.1:7000)
M: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots:0-5460 (5461 slots) master
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots: (0 slots) master
replicates 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4
M: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) master
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
M: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) master
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
复制代码

 

哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈。终于他妈的成功了!!!!

Redis-trib会提示你作了什么配置, 输入yes接受. 集群就被配置和加入了, 意思是, 实例会通过互相交流后启动。

测试集群的状态:

 
复制代码
[root@web3 7000]# redis-trib.rb check 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7004: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots: (0 slots) slave
replicates 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
复制代码

 

能够看到有3个主节点,3个从节点。每一个节点都是成功的链接状态。

3个主节点[M]是:

7000 (3707debcbe7be66d4a1968eaf3a5ffaf4308efa4) 
7001 (cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c) 
7002 (dfa0754c7854a874a6ebd2613b86140ad97701fc)

3个从节点[S]是:

7003 (d2237fdcfbba672de766b913d1186cebcb6e1761)->7000 
7004 (4b4aef8b48c427a3c903518339d53b6447c58b93)->7001 
7005 (30858dbf483b61b9838d5c1f853a60beaa4e7afd) ->7002

 

5. 测试链接集群

刚才集群搭建成功了。按照redis cluster的特色,它是去中心化,每一个节点都是对等的,因此,你链接哪一个节点均可以获取和设置数据,咱们来试一下。

redis-cli是redis默认的客户端工具,启动时加上`-c`参数,就能够链接到集群。

链接任意一个节点端口:

 
[root@web3 7000]# redis-cli -c -p 7000
127.0.0.1:7000>

设置一个值:

 
127.0.0.1:7000> set my_name yangyi
-> Redirected to slot [12803] located at 127.0.0.1:7002
OK
127.0.0.1:7002> get my_name
"yangyi"
127.0.0.1:7002>

前面理论知识咱们知道了,分配key的时候,它会使用CRC16('my_name')%16384算法,来计算,将这个key 放到哪一个节点,这里分配到了12803slot 就分配到了7002(10923-16383)这个节点上。

Redirected to slot [12803] located at 127.0.0.1:7002

redis cluster 采用的方式很直接,它直接跳转到7002 节点了,而不是还在自身的7000节点。

好,如今咱们链接7005这个节点:


[root@web3 7000]# redis-cli -c -p 7005
127.0.0.1:7005> get my_name
-> Redirected to slot [12803] located at 127.0.0.1:7002
"yangyi"
127.0.0.1:7002>

咱们一样是获取my_name的值,它一样也是跳转到了7002上。

咱们再尝试一些其余的能够:

 
复制代码
127.0.0.1:7002> set age 123
-> Redirected to slot [741] located at 127.0.0.1:7000
OK
127.0.0.1:7000> set height 565
-> Redirected to slot [8223] located at 127.0.0.1:7001
OK
127.0.0.1:7001> set sex 1
-> Redirected to slot [2584] located at 127.0.0.1:7000
OK
127.0.0.1:7000> set home china
-> Redirected to slot [10814] located at 127.0.0.1:7001
OK
127.0.0.1:7001> set city shanghai
-> Redirected to slot [11479] located at 127.0.0.1:7002
OK
127.0.0.1:7002> set citylocate shanghaipudong
OK
127.0.0.1:7001> set wsdwxzx hhh
-> Redirected to slot [15487] located at 127.0.0.1:7002
OK
127.0.0.1:7002> zadd erew 333 rrr
-> Redirected to slot [10576] located at 127.0.0.1:7001
(integer) 1
127.0.0.1:7000> zrange erew 0 -1
-> Redirected to slot [10576] located at 127.0.0.1:7001
1) "rrr"
127.0.0.1:7001>
复制代码

能够看出,数据都会在7000-7002 这3个主节点来跳转存粗。

6. 测试集群中的节点挂掉

上面咱们创建来了一个集群。3个主节点[7000-7002]提供数据存粗和读取,3个从节点[7003-7005]则是负责把[7000-7002]的数据同步到本身的节点上来,咱们来看一下[7003-7005]的appendonly.aof的内容。看看是否是不这样:

 
复制代码
[root@web3 7005]# cd /usr/local/cluster-test/7003
[root@web3 7003]# vi appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$3
age
$3
123
*3
$3
set
$3
sex
$1
1
*3
$3
set
$3
job
$3
php
复制代码

咱们看下,的确是从7000节点上同步过来的数据,7004,7005也是。

下面,咱们先来模拟其中一台Master主服务器挂掉的状况,那就7000挂掉吧:

 
复制代码
[root@web3 7003]# ps -ef|grep redis
root 11380 1 0 07:37 ? 00:00:03 redis-server *:7000 [cluster]
root 11384 1 0 07:37 ? 00:00:03 redis-server *:7001 [cluster]
root 11388 1 0 07:37 ? 00:00:03 redis-server *:7002 [cluster]
root 11392 1 0 07:37 ? 00:00:03 redis-server *:7003 [cluster]
root 11396 1 0 07:37 ? 00:00:04 redis-server *:7004 [cluster]
root 11400 1 0 07:37 ? 00:00:03 redis-server *:7005 [cluster]
[root@web3 7003]# kill 11380
[root@web3 7003]#
复制代码

好,安装前面的理论,7000主节点挂掉了,那么这个时候,7000的从节点只有7003一个,确定7003就会被选举称Master节点了:

 
复制代码
[root@web3 7003]# redis-trib.rb check 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: [ERR] Sorry, can't connect to node 127.0.0.1:7000
[root@web3 7003]# redis-trib.rb check 127.0.0.1:7001
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:0-5460 (5461 slots) master
0 additional replica(s)
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 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@web3 7003]#
复制代码

看了下,上面有了三个M 节点了,果然,7003被选取成了替代7000成为主节点了。那咱们来获取原先存在7000节点的数据:

 
[root@web3 7003]# redis-cli -c -p 7001
127.0.0.1:7001> get sex
-> Redirected to slot [2584] located at 127.0.0.1:7003
"1"
127.0.0.1:7003>

数据果然没有丢失,而是从7003上面获取了。

OK。咱们再来模拟 7000节点从新启动了的状况,那么它还会自动加入到集群中吗?那么,7000这个节点上充当什么角色呢? 咱们试一下:

从新启动 7000 节点:

     
复制代码
[root@web3 7003]# cd ../7000
[root@web3 7000]# ll
total 56
-rw-r--r-- 1 root root 114 Oct 17 08:16 appendonly.aof
-rw-r--r-- 1 root root 43 Oct 17 08:37 dump.rdb
-rw-r--r-- 1 root root 745 Oct 17 08:00 nodes.conf
-rw-r--r-- 1 root root 41550 Oct 17 07:37 redis.conf
[root@web3 7000]# redis-server redis.conf
复制代码

 

     启动好了,如今,再来检查一下集群:
 
复制代码
redis-trib.rb check 127.0.0.1:700`
 
[root@web3 7000]# redis-trib.rb check 127.0.0.1:7001
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:0-5460 (5461 slots) master
1 additional replica(s)
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 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.
复制代码

你看,7000节点启动起来了,它却做为了 70003 的从节点了。验证了以前的这张图:

这里写图片描述

必定要保证有3个master 节点,否则,集群就挂掉了。

 

7. 集群中新加入节点

咱们再来测试一下,新加入一个节点,分2种状况,1是做为主节点,2是做为一个节点的从节点。咱们分别来试一下:

1. 新建一个 7006 节点 做为一个新的主节点加入:

首先就是新建一个 7006的文件夹和redis.conf:

 
[root@web3 cluster-test]# cd /usr/local/cluster-test/
[root@web3 cluster-test]# mkdir 7006
[root@web3 cluster-test]# cp 7005/redis.conf 7006/redis.conf
#修改端口
[root@web3 cluster-test]sed -i "s/7005/7006/g" /usr/local/cluster-test/7006/redis.conf

启动 7006 

复制代码
[root@web3 7006]# redis-server redis.conf
[root@web3 7006]# ps -ef|grep redis
root 11384 1 0 07:37 ? 00:00:05 redis-server *:7001 [cluster]
root 11388 1 0 07:37 ? 00:00:05 redis-server *:7002 [cluster]
root 11392 1 0 07:37 ? 00:00:05 redis-server *:7003 [cluster]
root 11396 1 0 07:37 ? 00:00:06 redis-server *:7004 [cluster]
root 11400 1 0 07:37 ? 00:00:05 redis-server *:7005 [cluster]
root 12100 1 0 08:42 ? 00:00:01 redis-server *:7000 [cluster]
root 12132 1 0 09:09 ? 00:00:00 redis-server *:7006 [cluster]
root 12136 8259 0 09:10 pts/0 00:00:00 grep redis
复制代码

ok,7006 端口已经启动好了,而且进程也存在了,下面就是加入到集群中,也是得用到redis-trib.rb命令:

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

add-node是加入指令,127.0.0.1:7006 表示新加入的节点,127.0.0.1:7000 表示加入的集群的一个节点,用来辨识是哪一个集群,理论上哪一个均可以。

 
复制代码
[root@web3 7006]# redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
>>> Adding node 127.0.0.1:7006 to cluster 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 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.
Connecting to node 127.0.0.1:7006: OK
>>> Send CLUSTER MEET to node 127.0.0.1:7006 to make it join the cluster.
[OK] New node added correctly.
复制代码
    
这个命令执行完成以后,它顺便检查来其余的6个节点都是成功的,最后几句话:
 
Connecting to node 127.0.0.1:7006: OK
>>> Send CLUSTER MEET to node 127.0.0.1:7006 to make it join the cluster.
[OK] New node added correctly.

表示新的节点链接成功了,并且也已经加入到集群了,咱们再来检查一下:

复制代码
[root@web3 7006]# redis-trib.rb check 127.0.0.1:7006
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
>>> Performing Cluster Check (using node 127.0.0.1:7006)
M: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
slots: (0 slots) master
0 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:0-5460 (5461 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.
复制代码

 

 
能够看到了,7006 已经成为了主节点。

咱们也能够链接到客户端后,来看这个集群节点状况:

 
复制代码
[root@web3 7006]# redis-cli -c -p 7006
127.0.0.1:7006> cluster nodes
cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001 master - 0 1445073797986 2 connected 5461-10922
4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004 slave cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 0 1445073799497 2 connected
efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006 myself,master - 0 0 0 connected
3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000 slave d2237fdcfbba672de766b913d1186cebcb6e1761 0 1445073797482 7 connected
dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002 master - 0 1445073798489 3 connected 10923-16383
30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005 slave dfa0754c7854a874a6ebd2613b86140ad97701fc 0 1445073798993 3 connected
d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003 master - 0 1445073799498 7 connected 0-5460
127.0.0.1:7006>
复制代码

能够看到 有7个节点。7006 也做为了master节点,可是,可是,你看看后面的:

 
efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
slots: (0 slots) master

卧槽,什么状况。o slots 也就是说,虽然它如今是主节点,可是,缺没有分配任何节点给它,也就是它如今还不负责数据存取。那加上去有毛用啊!!!!

看来,redis cluster 不是在新加节点的时候帮咱们作好了迁移工做,须要咱们手动对集群进行从新分片迁移,也是这个命令:

redis-trib.rb reshard 127.0.0.1:7000

这个命令是用来迁移slot节点的,后面的127.0.0.1:7000是表示是哪一个集群,端口填[7000-7006]均可以,咱们运行下:

 
  1. 复制代码
    [root@web3 7006]# redis-trib.rb reshard 127.0.0.1:7000
    Connecting to node 127.0.0.1:7006: OK
    Connecting to node 127.0.0.1:7001: OK
    Connecting to node 127.0.0.1:7004: OK
    Connecting to node 127.0.0.1:7000: OK
    Connecting to node 127.0.0.1:7002: OK
    Connecting to node 127.0.0.1:7005: OK
    Connecting to node 127.0.0.1:7003: OK
    >>> Performing Cluster Check (using node 127.0.0.1:7006)
    M: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
    slots: (0 slots) master
    0 additional replica(s)
    M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
    slots:5461-10922 (5462 slots) master
    1 additional replica(s)
    S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
    slots: (0 slots) slave
    replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
    S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
    slots: (0 slots) slave
    replicates d2237fdcfbba672de766b913d1186cebcb6e1761
    M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
    slots:10923-16383 (5461 slots) master
    1 additional replica(s)
    S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
    slots: (0 slots) slave
    replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
    M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
    slots:0-5460 (5461 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.
    How many slots do you want to move (from 1 to 16384)?
    复制代码

它提示咱们须要迁移多少slot到7006上,咱们能够算一下:16384/4 = 4096,也就是说,为了平衡分配起见,咱们须要移动4096个槽点到7006上。

好,那输入4096:

 
How many slots do you want to move (from 1 to 16384)? 4096
What is the receiving node ID?

它又提示咱们,接受的node ID是多少,7006的id 咱们经过上面就能够看到是efc3131fbdc6cf929720e0e0f7136cae85657481 :

 
What is the receiving node ID? efc3131fbdc6cf929720e0e0f7136cae85657481
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1:

接着, redis-trib 会向你询问从新分片的源节点(source node), 也便是, 要从哪一个节点中取出 4096 个哈希槽, 并将这些槽移动到7006节点上面。

若是咱们不打算从特定的节点上取出指定数量的哈希槽, 那么能够向 redis-trib 输入 all , 这样的话, 集群中的全部主节点都会成为源节点, redis-trib 将从各个源节点中各取出一部分哈希槽, 凑够 4096 个, 而后移动到7006节点上:

 
Source node #1:all

接下来就开始迁移了,而且会询问你是否确认:

复制代码
Moving slot 1359 from d2237fdcfbba672de766b913d1186cebcb6e1761
Moving slot 1360 from d2237fdcfbba672de766b913d1186cebcb6e1761
Moving slot 1361 from d2237fdcfbba672de766b913d1186cebcb6e1761
Moving slot 1362 from d2237fdcfbba672de766b913d1186cebcb6e1761
Moving slot 1363 from d2237fdcfbba672de766b913d1186cebcb6e1761
Moving slot 1364 from d2237fdcfbba672de766b913d1186cebcb6e1761
Do you want to proceed with the proposed reshard plan (yes/no)?
复制代码
输入 yes 并使用按下回车以后, redis-trib 就会正式开始执行从新分片操做, 将指定的哈希槽从源节点一个个地移动到7006节点上面。

迁移完毕以后,咱们来检查下:

 
复制代码
[root@web3 7006]# redis-trib.rb check 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
M: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
slots:0-1364,5461-6826,10923-12287 (4096 slots) master
0 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:1365-5460 (4096 slots) master
1 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:6827-10922 (4096 slots) master
1 additional replica(s)
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:12288-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.
复制代码

咱们着重看7006:

0-1364,5461-6826,10923-12287 (4096 slots)

这些原来在其余节点上的slot 杯迁移到了7006上。原来,它只是间隔的移动,并非衔接的总体移动,咱们看下有数据了没?

 
复制代码
[root@web3 7006]# redis-cli -c -p 7006
127.0.0.1:7006> keys *
1) "city"
2) "age"
3) "citylocate"
127.0.0.1:7006> get city
"shanghai"
复制代码

很是赞,已经有数据了。

 
2. 新建一个 7007从节点,做为7006的从节点

咱们再新建一个节点7007,步骤相似,就先省略了。建好后,启动起来,咱们看如何把它加入到集群中的从节点中:

[root@web3 7007]# redis-trib.rb add-node --slave 127.0.0.1:7007 127.0.0.1:7000
的时候加上表示是加入到从节点中,可是这样加,是随机的。这里的命令行彻底像咱们在添加一个新主服务器时使用的同样,因此咱们没有指定要给哪一个主服 务器添加副本。这种状况下, 会将做为一个具备较少副本的随机的主服务器的副本。add-node--slaveredis-trib7007

那么,你猜,它会做为谁的从节点,应该是7006,由于7006尚未从节点。咱们运行下。

 
复制代码
[root@web3 7007]# redis-trib.rb add-node --slave 127.0.0.1:7007 127.0.0.1:7000
...
...
[OK] All 16384 slots covered.
Automatically selected master 127.0.0.1:7006
Connecting to node 127.0.0.1:7007: OK
>>> Send CLUSTER MEET to node 127.0.0.1:7007 to make it join the cluster.
Waiting for the cluster to join.
>>> Configure node as replica of 127.0.0.1:7006.
[OK] New node added correctly.
复制代码

上面提示说,自动选择了7006做为master节点。而且成功了。咱们检查下:

 
复制代码
[root@web3 7007]# redis-trib.rb check 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7007: OK
Connecting to node 127.0.0.1:7002: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
M: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
slots:0-1364,5461-6826,10923-12287 (4096 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:1365-5460 (4096 slots) master
1 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:6827-10922 (4096 slots) master
1 additional replica(s)
S: 86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007
slots: (0 slots) slave
replicates efc3131fbdc6cf929720e0e0f7136cae85657481
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:12288-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.
复制代码

果真,7007加入到了7006的从节点当中。

你说,我若是想指定一个主节点行不行?固然能够。咱们再建一个7008节点。

 
复制代码
redis-trib.rb add-node --slave --master-id efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7008 127.0.0.1:7000
--master-id 表示指定的主节点node id。这里指定的是 7006 这个主节点。

 
Waiting for the cluster to join.
>>> Configure node as replica of 127.0.0.1:7006.
[OK] New node added correctly.
[root@web3 7008]#
复制代码

提示咱们已经做为7006的附属品,也就是加入到7006的从节点来了,照这么说,7006就有2个从节点了,咱们看一下:

 
redis-cli -c -p 7008 cluster nodes |grep efc3131fbdc6cf929720e0e0f7136cae85657481
86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007 slave efc3131fbdc6cf929720e0e0f7136cae85657481 0 1445089507786 8 connected
efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006 master - 0 1445089508289 8 connected 0-1364 5461-6826 10923-12287
44321e7d619410dc4e0a8745366610a0d06d2395 127.0.0.1:7008 myself,slave efc3131fbdc6cf929720e0e0f7136cae85657481 0 0 0 connected

咱们过滤了下看结果,果然,7007和7008是7006的从节点了。

恰好,咱们再作一个实验,我把7006的杀掉,看7007和7008谁会变成主节点:

 
  1. 复制代码
    [root@web3 7008]# ps -ef|grep redis
    root 11384 1 0 09:56 ? 00:00:16 redis-server *:7001 [cluster]
    root 11388 1 0 09:56 ? 00:00:16 redis-server *:7002 [cluster]
    root 11392 1 0 09:56 ? 00:00:16 redis-server *:7003 [cluster]
    root 11396 1 0 09:56 ? 00:00:15 redis-server *:7004 [cluster]
    root 11400 1 0 09:56 ? 00:00:15 redis-server *:7005 [cluster]
    root 12100 1 0 11:01 ? 00:00:11 redis-server *:7000 [cluster]
    root 12132 1 0 11:28 ? 00:00:11 redis-server *:7006 [cluster]
    root 12202 1 0 13:14 ? 00:00:02 redis-server *:7007 [cluster]
    root 12219 1 0 13:39 ? 00:00:00 redis-server *:7008 [cluster]
    root 12239 8259 0 13:49 pts/0 00:00:00 grep redis
    [root@web3 7008]# kill 12132
    [root@web3 7008]# redis-cli -c -p 7008
    127.0.0.1:7008> get ss5rtr
    -> Redirected to slot [1188] located at 127.0.0.1:7007
    "66"
    127.0.0.1:7007> cluster nodes
    efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006 master,fail - 1445089780668 1445089779963 8 disconnected
    d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003 master - 0 1445089812195 7 connected 1365-5460
    30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005 slave dfa0754c7854a874a6ebd2613b86140ad97701fc 0 1445089813710 3 connected
    86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007 myself,master - 0 0 10 connected 0-1364 5461-6826 10923-12287
    cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001 master - 0 1445089814214 2 connected 6827-10922
    4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004 slave cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 0 1445089812701 2 connected
    44321e7d619410dc4e0a8745366610a0d06d2395 127.0.0.1:7008 slave 86d05e7c2b197dc182b5e71069e791d033cf899e 0 1445089814214 10 connected
    3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000 slave d2237fdcfbba672de766b913d1186cebcb6e1761 0 1445089813204 7 connected
    dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002 master - 0 1445089813204 3 connected 12288-16383
    127.0.0.1:7007>
    复制代码

     

看,7007得到了成为主节点的机会,7008就变成了7007的从节点。

那么这个时候,重启7006节点,那么他就会变成了一个7007的从节点了。

 
复制代码
27.0.0.1:7008> cluster nodes
30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005 slave dfa0754c7854a874a6ebd2613b86140ad97701fc 0 1445089986148 3 connected
86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007 master - 0 1445089986652 10 connected 0-1364 5461-6826 10923-12287
d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003 master - 0 1445089986148 7 connected 1365-5460
cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001 master - 0 1445089987155 2 connected 6827-10922
efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006 slave 86d05e7c2b197dc182b5e71069e791d033cf899e 0 1445089985644 10 connected
44321e7d619410dc4e0a8745366610a0d06d2395 127.0.0.1:7008 myself,slave 86d05e7c2b197dc182b5e71069e791d033cf899e 0 0 0 connected
dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002 master - 0 1445089986652 3 connected 12288-16383
4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004 slave cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 0 1445089987660 2 connected
3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000 slave d2237fdcfbba672de766b913d1186cebcb6e1761 0 1445089985644 7 connected
127.0.0.1:7008>
复制代码
3. 移除一个主节点

有加确定有减,redis cluster一样支持移除节点功能,一样也是redis-trib.rb的用法:

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

和新加节点有点不一样的是,移除须要节点的node-id。那咱们尝试将7007这个主节点移除:

 
复制代码
[root@web3 7006]# redis-trib.rb del-node 127.0.0.1:7000 86d05e7c2b197dc182b5e71069e791d033cf899e
>>> Removing node 86d05e7c2b197dc182b5e71069e791d033cf899e from cluster 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7007: OK
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7002: OK
[ERR] Node 127.0.0.1:7007 is not empty! Reshard data away and try again.
复制代码

报错了,它提示咱们说,因为7007里面已经有数据了,不能被移除,要先将它的数据转移出去。也就是说得从新分片,用上面增长新节点后的分片方式同样,用咱们再来一遍:

redis-trib.rb reshard 127.0.0.1:7000

因为中间太多内容,就省略不重要的,只简单说明下关键的几步:

 
M: 86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007
slots:0-1364,5461-6826,10923-12287 (4096 slots) master
How many slots do you want to move (from 1 to 16384)?

提示,咱们要分多少个槽点,因为7007上有4096个槽点,因此这里填写4096

 
How many slots do you want to move (from 1 to 16384)? 4096
What is the receiving node ID?

提示咱们,须要移动到哪一个id上,那就填7001的吧:

 
What is the receiving node ID? cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
Please enter all the source node IDs.
Type 'all' to use all the nodes as source nodes for the hash slots.
Type 'done' once you entered all the source nodes IDs.
Source node #1:

这里就是关键了,它要咱们从哪一个节点去转移数据到7001,由于咱们是要删除7007的,因此,咱们就得7007的id了

 
Source node #1:86d05e7c2b197dc182b5e71069e791d033cf899e
Source node #2:done
Do you want to proceed with the proposed reshard plan (yes/no)? yes

ok,这样就迁移好了。咱们看看7007是否为空了:

 
[root@web3 7006]# redis-cli -c -p 7007
127.0.0.1:7007> keys *
(empty list or set)
127.0.0.1:7007> cluster nodes
86d05e7c2b197dc182b5e71069e791d033cf899e 127.0.0.1:7007 myself,master - 0 0 10 connected

果真为空了,好。如今再进行移除节点操做:

 
复制代码
[root@web3 7006]# redis-trib.rb del-node 127.0.0.1:7000 86d05e7c2b197dc182b5e71069e791d033cf899e
>>> Removing node 86d05e7c2b197dc182b5e71069e791d033cf899e from cluster 127.0.0.1:7000
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7007: OK
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7002: OK
>>> Sending CLUSTER FORGET messages to the cluster...
>>> 127.0.0.1:7006 as replica of 127.0.0.1:7001
>>> 127.0.0.1:7008 as replica of 127.0.0.1:7001
>>> SHUTDOWN the node.
复制代码

哈哈哈哈哈,删除成功,并且还很人性化的将700670082个没了爹的孩子送给了7001。好评👌

咱们再检查一下:7007 已经移除,连不上了。

 
复制代码
[root@web3 7006]# redis-trib.rb check 127.0.0.1:7007
Connecting to node 127.0.0.1:7007: [ERR] Sorry, can't connect to node 127.0.0.1:7007
 
[root@web3 7006]# redis-trib.rb check 127.0.0.1:7008
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7003: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7000: OK
>>> Performing Cluster Check (using node 127.0.0.1:7008)
S: 44321e7d619410dc4e0a8745366610a0d06d2395 127.0.0.1:7008
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 30858dbf483b61b9838d5c1f853a60beaa4e7afd 127.0.0.1:7005
slots: (0 slots) slave
replicates dfa0754c7854a874a6ebd2613b86140ad97701fc
M: d2237fdcfbba672de766b913d1186cebcb6e1761 127.0.0.1:7003
slots:1365-5460 (4096 slots) master
1 additional replica(s)
M: cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c 127.0.0.1:7001
slots:0-1364,5461-12287 (8192 slots) master
3 additional replica(s)
S: efc3131fbdc6cf929720e0e0f7136cae85657481 127.0.0.1:7006
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
M: dfa0754c7854a874a6ebd2613b86140ad97701fc 127.0.0.1:7002
slots:12288-16383 (4096 slots) master
1 additional replica(s)
S: 4b4aef8b48c427a3c903518339d53b6447c58b93 127.0.0.1:7004
slots: (0 slots) slave
replicates cb5c04b6160c3b7e18cad5d49d8e2987b27e0d6c
S: 3707debcbe7be66d4a1968eaf3a5ffaf4308efa4 127.0.0.1:7000
slots: (0 slots) slave
replicates d2237fdcfbba672de766b913d1186cebcb6e1761
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
[root@web3 7006]#
复制代码

70067008果真也成功加入到了7001的你们庭。

 
4. 移除一个从节点

移除一个从节点就简单的多了,由于不须要考虑数据的迁移,咱们7008给移除:

 
复制代码
[root@web3 7006]# redis-trib.rb del-node 127.0.0.1:7005 44321e7d619410dc4e0a8745366610a0d06d2395
>>> Removing node 44321e7d619410dc4e0a8745366610a0d06d2395 from cluster 127.0.0.1:7005
Connecting to node 127.0.0.1:7005: OK
Connecting to node 127.0.0.1:7001: OK
Connecting to node 127.0.0.1:7002: OK
Connecting to node 127.0.0.1:7004: OK
Connecting to node 127.0.0.1:7000: OK
Connecting to node 127.0.0.1:7006: OK
Connecting to node 127.0.0.1:7008: OK
Connecting to node 127.0.0.1:7003: OK
>>> Sending CLUSTER FORGET messages to the cluster...
>>> SHUTDOWN the node.
[root@web3 7006]# redis-trib.rb check 127.0.0.1:7008
Connecting to node 127.0.0.1:7008: [ERR] Sorry, can't connect to node 127.0.0.1:7008
复制代码

 

移除成功。

 

redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比 

 

张旭峰
  张旭峰 发布于 2017/05/21 01:32
 
字数 5452
 
阅读 3540
 
收藏  140
 
点赞  7
 
 评论 9
 

      redis做为一种高效的缓存框架,使用是很是普遍的,在数据存储上,在运行时其将数据存储在内存中,以实现数据的高效读写,而且根据定制的持久化规则不一样,其会不按期的将数据持久化到硬盘中。另外相较于其余的NoSql数据库,redis提供了很是丰富的数据结构,如dict,sds,linkedlist,ziplist,set,quicklist,geometry。在这些存储结构的基础上,redis为用户提供了很是丰富的操做选择,如经过zskiplist来达到对某种类型的数据的排序目的,而排序在数据库中是一个很是耗时的操做。

1.redis单例的安装和使用

      redis相对于其余的缓存框架安装很是的方便,只须要从https://redis.io/download下载后解压,进入redis目录以后执行以下命令即安装完成:

make install

这里须要注意的是make是gcc中的一个命令,安装以前请确保机器安装了gcc。redis中全部的命令都在redis安装目录中的src子目录下,其中比较重要的是redis-server,redis-sentinel,redis-cli。

      编译完成以后在src目录下执行./redis-server启动redis(启动后可关闭该窗口),而后新开一个窗口,在命令行中执行./redis-cli便可链接启动的redis服务。在其中执行以下命令便可看到编译安装成功了:

127.0.0.1:6379> set hello world OK 127.0.0.1:6379> get hello "world"

      这里须要说明的是,按照上述方式启动redis,其使用的ip为本机ip 127.0.0.1,端口为6379,而且其他的配置采用的都是默认配置,相关配置可在redis安装目录下的redis.conf文件中查看。若是须要按照指定的配置文件来启动,可在redis-server后接上配置文件名,如:

./src/redis-server redis.conf

另外,上述使用redis-cli链接redis客户端时若是不带任何参数,那么其链接的默认ip和端口为127.0.0.1:6379。若是须要链接指定ip和端口的客户端,可使用以下方式:

./src/redis-cli -h 127.0.0.1 -p 6379

这里-h参数表示链接的ip,-p则表示链接的端口。

      配置好redis以后,咱们就能够在redis中执行相关命令来操做数据,关于redis的经常使用命令,可查看本人的另外一篇博客《redis经常使用命令大全》,其中有比较详细的讲解。

2.redis主从模式的配置

      redis单例提供了一种数据缓存方式和丰富的数据操做api,可是将数据彻底存储在单个redis中主要存在两个问题:数据备份和数据体量较大形成的性能下降。这里redis的主从模式为这两个问题提供了一个较好的解决方案。主从模式指的是使用一个redis实例做为主机,其他的实例做为备份机。主机和从机的数据彻底一致,主机支持数据的写入和读取等各项操做,而从机则只支持与主机数据的同步和读取,也就是说,客户端能够将数据写入到主机,由主机自动将数据的写入操做同步到从机。主从模式很好的解决了数据备份问题,而且因为主从服务数据几乎是一致的,于是能够将写入数据的命令发送给主机执行,而读取数据的命令发送给不一样的从机执行,从而达到读写分离的目的。以下所示主机redis-A分别有redis-B、redis-C、redis-D、redis-E四个从机:

      前面第1点中咱们已经介绍了redis单例的配置方式,而上面咱们也介绍了主从模式其实也是多个redis实例组成的,于是redis主从模式的配置能够理解为多个不一样的redis实例经过必定的配置告知其相互之间的主从关系。而前面已经介绍,每一个redis实例都会占用一个本机的端口号,主从模式的配置主要的配置点有两个:当前实例端口号和当前实例是主机仍是从机,是从机的话其主机的ip和端口是什么。通常的redis目录下的redis.conf保存的是默认配置,尽可能不要对其进行修改,这里咱们复制三份redis.conf文件,分别命名为6379.conf,6380.conf和6381.conf,以下是端口为6379的主机的主要配置:

bind 127.0.0.1 port 6379 logfile "6379.log" dbfilename "dump-6379.rdb"

以下是端口为6380和6381的从机的配置:

bind 127.0.0.1 port 6380 logfile "6380.log" dbfilename "dump-6380.rdb" slaveof 127.0.0.1 6379
bind 127.0.0.1 port 6381 logfile "6381.log" dbfilename "dump-6381.rdb" slaveof 127.0.0.1 6379

      能够看到,端口为6380和6381的实例被配置为端口为6379的实例的从机。配置完成后使用redis-server分别执行以下命令启动三个实例:

./src/redis-server 6379.conf ./src/redis-server 6380.conf ./src/redis-server 6381.conf

启动以后分别开启开启三个命令行工具分别执行如下命令链接redis实例:

./src/redis-cli -p 6379 ./src/redis-cli -p 6380 ./src/redis-cli -p 6381

分别在三个命令行工具中执行一个get命令,获取键名为msg的数据,以下所示:

127.0.0.1:6379> get msg (nil)
127.0.0.1:6380> get msg (nil)
127.0.0.1:6381> get msg (nil)

能够看到,在三个redis实例中都不存在键为msg的数据,如今咱们在主机6379上设置一个键为msg的数据,以下所示:

127.0.0.1:6379> set msg "hello" OK

能够看到设置成功了,此时咱们在6380和6381的实例上执行get msg的命令,以下所示:

127.0.0.1:6380> get msg "hello"
127.0.0.1:6381> get msg "hello"

能够看到,虽然咱们只是在6379的实例上设置了msg这条数据,可是在6380和6381的实例上也存有了相应的数据,说明咱们成功配置了redis的主从模式。另外,若是不在配置文件中指定主从节点的关系,也能够在启动相关redis实例以后使用slaveof命令来指定当前节点称为某个节点的从节点,如:

127.0.0.1:6380> slaveof 127.0.0.1 6379

3.redis中sentinel配置

      redis主从模式解决了数据备份和单例可能存在的性能问题,可是其也引入了新的问题。因为主从模式配置了三个redis实例,而且每一个实例都使用不一样的ip(若是在不一样的机器上)和端口号,根据前面所述,主从模式下能够将读写操做分配给不一样的实例进行从而达到提升系统吞吐量的目的,但也正是由于这种方式形成了使用上的不便,由于每一个客户端链接redis实例的时候都是指定了ip和端口号的,若是所链接的redis实例由于故障下线了,而主从模式也没有提供必定的手段通知客户端另外可链接的客户端地址,于是须要手动更改客户端配置从新链接。另外,主从模式下,若是主节点因为故障下线了,那么从节点由于没有主节点而同步中断,于是须要人工进行故障转移工做。

      为了解决这两个问题,在2.8版本以后redis正式提供了sentinel(哨兵)架构。关于sentinel,这里须要说明几个概念:

名词 逻辑结构 物理结构
主节点 redis主服务/数据库 一个独立的redis进程
从节点 redis从服务/数据库 一个独立的redis进程
sentinel节点 监控redis数据节点 一个独立的sentinel进程
sentinel节点集合 若干sentinel节点的抽象集合 若干sentinel节点进程
应用方 泛指一个或多个客户端 一个或多个客户端线程或进程

      每一个sentinel节点其实就是一个redis实例,与主从节点不一样的是sentinel节点做用是用于监控redis数据节点的,而sentinel节点集合则表示监控一组主从redis实例多个sentinel监控节点的集合,好比有主节点master和从节点slave-一、slave-2,为了监控这三个主从节点,这里配置N个sentinel节点sentinel-1,sentinel-2,...,sentinel-N。以下图是sentinel监控主从节点的示例图:

      从图中能够看出,对于一组主从节点,sentinel只是在其外部额外添加的一组用于监控做用的redis实例。在主从节点和sentinel节点集合配置好以后,sentinel节点之间会相互发送消息,以检测其他sentinel节点是否正常工做,而且sentinel节点也会向主从节点发送消息,以检测监控的主从节点是否正常工做。。前面讲到,sentinel架构的主要做用是解决主从模式下主节点的故障转移工做的。这里若是主节点由于故障下线,那么某个sentinel节点发送检测消息给主节点时,若是在指定时间内收不到回复,那么该sentinel就会主观的判断该主节点已经下线,那么其会发送消息给其他的sentinel节点,询问其是否“认为”该主节点已下线,其他的sentinel收到消息后也会发送检测消息给主节点,若是其认为该主节点已经下线,那么其会回复向其询问的sentinel节点,告知其也认为主节点已经下线,当该sentinel节点最早收到超过指定数目(配置文件中配置的数目和当前sentinel节点集合数的一半,这里两个数目的较大值)的sentinel节点回复说当前主节点已下线,那么其就会对主节点进行故障转移工做,故障转移的基本思路是在从节点中选取某个从节点向其发送slaveof no one(假设选取的从节点为127.0.0.1:6380),使其称为独立的节点(也就是新的主节点),而后sentinel向其他的从节点发送slaveof 127.0.0.1 6380命令使它们从新成为新的主节点的从节点。从新分配以后sentinel节点集合还会继续监控已经下线的主节点(假设为127.0.0.1:6379),若是其从新上线,那么sentinel会向其发送slaveof命令,使其成为新的主机点的从节点,如此故障转移工做完成。

      上面咱们讲到了,每一个sentinel节点在本质上仍是一个redis实例,只不过和redis数据节点不一样的是,其主要做用是监控redis数据节点。在redis安装目录下有个默认的sentinel配置文件sentinel.conf,和配置主从节点相似,这里复制三个配置文件:sentinel-26379.conf,sentinel-26380.conf和sentinel-26381.conf。分别按照以下示例编辑这三个配置文件:

port 26379 daemonize yes logfile "26379.log" dir /opt/soft/redis/data sentinel monitor mymaster 127.0.0.1 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 sentinel myid mm55d2d712b1f3f312b637f9b546f00cdcedc787

对于端口为26380和26381的sentinel,其配置和上述相似,只须要把相应的端口号修改成对应的端口号便可。这里注意两点:①每一个sentinel的myid参数也要进行修改,由于sentinel之间是经过该属性来惟一区分其余sentinel节点的;②参数中sentinel monitor mymaster 127.0.0.1 6379 2这里的端口号6379是不用更改的,由于sentinel是经过检测主节点的状态来得知当前主节点的从节点有哪些的,于是设置为主节点的端口号便可。配置完成后咱们首先启动三个主从节点,而后分别使用三个配置文件使用以下命令启用sentinel:

./src/redis-sentinel sentinel-26379.conf ./src/redis-sentinel sentinel-26380.conf ./src/redis-sentinel sentinel-26381.conf

因为sentinel节点也是一个redis实例,于是咱们能够经过以下命令使用redis-cli链接sentinel节点:

./src/redis-cli -p 26379

连上sentinel节点以后咱们能够经过以下命令查看sentinel状态:

127.0.0.1:26379> info sentinel

结果以下:

# Sentinel
sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3

能够看到,sentinel检测到主从节点总共有三个,其中一个主节点,两个从节点,而且sentinel节点总共也有三个。启动完成以后,咱们能够经过主动下线主节点来模拟sentinel的故障转移过程。首先咱们链接上端口为6379的主节点,使用以下命令查看主从节点状态:

127.0.0.1:6379> info replication

结果以下:

# Replication
role:master
connected_slaves:2 slave0:ip=127.0.0.1,port=6380,state=online,offset=45616,lag=1 slave1:ip=127.0.0.1,port=6381,state=online,offset=45616,lag=1 master_repl_offset:45616 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:45615

能够看到,当前主节点有两个从节点,端口分别为6380和6381。而后咱们对主节点执行以下命令:

127.0.0.1:6379> shutdown save

而后咱们链接上端口号为6380的从节点,并执行以下命令:

127.0.0.1:6380> info replication 

结果以下:

# Replication
role:master
connected_slaves:1 slave0:ip=127.0.0.1,port=6381,state=online,offset=12344,lag=0 master_repl_offset:12477 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:12476

能够看到,当端口为6379的实例下线以后,端口为6380的实例被从新竞选为新的主节点,而且端口为6381的实例被设置为6380的实例的从节点。若是咱们此时从新启用端口为6379的节点,而后再查看主从状态,结果以下:

# Replication
role:master
connected_slaves:2 slave0:ip=127.0.0.1,port=6381,state=online,offset=59918,lag=0 slave1:ip=127.0.0.1,port=6379,state=online,offset=59918,lag=1 master_repl_offset:60051 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:60050

能够看到,端口为6379的redis实例从新链接后,sentinel节点检测到其从新链接,那么对其发送命令,使其成为新的主节点的从节点。

4.redis集群的配置

      redis集群是在redis 3.0版本推出的一个功能,其有效的解决了redis在分布式方面的需求。当遇到单机内存,并发和流量瓶颈等问题时,可采用Cluster方案达到负载均衡的目的。而且从另外一方面讲,redis中sentinel有效的解决了故障转移的问题,也解决了主节点下线客户端没法识别新的可用节点的问题,可是若是是从节点下线了,sentinel是不会对其进行故障转移的,而且链接从节点的客户端也没法获取到新的可用从节点,而这些问题在Cluster中都获得了有效的解决。

      redis集群中数据是和槽(slot)挂钩的,其总共定义了16384个槽,全部的数据根据一致哈希算法会被映射到这16384个槽中的某个槽中;另外一方面,这16384个槽是按照设置被分配到不一样的redis节点上的,好比启动了三个redis实例:cluster-A,cluster-B和cluster-C,这里将0-5460号槽分配给cluster-A,将5461-10922号槽分配给cluster-B,将10923-16383号槽分配给cluster-C(总共有16384个槽,可是其标号相似数组下标,是从0到16383)。也就是说数据的存储只和槽有关,而且槽的数量是必定的,因为一致hash算法是必定的,于是将这16384个槽分配给不管多少个redis实例,对于确认的数据其都将被分配到肯定的槽位上。redis集群经过这种方式来达到redis的高效和高可用性目的。

      这里须要进行说明的一点是,一致哈希算法根据数据的key值计算映射位置时和所使用的节点数量有很是大的关系。一致哈希分区的实现思路是为系统中每一个节点分配一个token,范围通常在0~2^32,这些token构成一个哈希环,数据读写执行节点查找操做时,先根据key计算hash值,而后顺时针找到第一个大于等于该hash值的token节点,须要操做的数据就保存在该节点上。经过分析能够发现,一致哈希分区存在以下问题:

  1. 加减节点会形成哈希环中部分数据没法命中,须要手动处理或忽略这部分数据;
  2. 当使用少许节点时,节点变化将大范围影响环中数据映射,所以这种方式不适合少许节点的分布式方案;
  3. 普通的一致性哈希分区在增减节点时须要增长一倍或减去一半节点才能保证数据和负载的平衡。

正是因为一致哈希分区的这些问题,redis使用了虚拟槽来处理分区时节点变化的问题,也即将全部的数据映射到16384个虚拟槽位上,当redis节点变化时数据映射的槽位将不会变化,而且这也是redis进行节点扩张的基础。

      对于redis集群的配置,首先将redis安装目录下的redis.conf文件复制六份,分别取名为:cluster-6379.conf、cluster-6380.conf、cluster-6381.conf、cluster-6382.conf、cluster-6383.conf、cluster-6384.conf。对于一个高可用的集群方案,集群每一个节点都将为其分配一个从节点,以防止数据节点由于故障下线,这里使用六份配置文件定义六个redis实例,其中三个做为主节点,剩余三个分别做为其从节点。对于这六份配置文件,以其中一份为例,如下是其须要修改的参数:

port 6379 cluster-enabled yes cluster-node-timeout 15000 cluster-config-file "nodes-6379.conf" pidfile /var/run/redis_6379.pid logfile "cluster-6379.log" dbfilename dump-cluster-6379.rdb appendfilename "appendonly-cluster-6379.aof"

对于其他的配置文件,只须要将其中对应项的端口号和带有端口号的文件名修改成当前要指定的端口号和端口号的文件名便可。配置文件配置好以后使用以下命令启动集群中的每一个实例:

./src/redis-server cluster-6379.conf ./src/redis-server cluster-6380.conf ./src/redis-server cluster-6381.conf ./src/redis-server cluster-6382.conf ./src/redis-server cluster-6383.conf ./src/redis-server cluster-6384.conf

仔细阅读上述配置文件可发现,当前配置和启动过程当中并无指定这六个实例的主从关系,也没有对16384个槽位进行分配。于是咱们还须要进行进一步的配置,槽位的分配和主从关系的设定有两种方式进行,一种是使用redis-cli链接到集群节点上后使用cluster meet命令链接其余的节点,如咱们首先执行以下命令链接到6379端口的节点:

./src/redis-cli -p 6379

链接上后使用cluster meet命令分别链接其他节点:

127.0.0.1:6379>cluster meet 127.0.0.1 6380 127.0.0.1:6379>cluster meet 127.0.0.1 6381 127.0.0.1:6379>cluster meet 127.0.0.1 6382 127.0.0.1:6379>cluster meet 127.0.0.1 6383 127.0.0.1:6379>cluster meet 127.0.0.1 6384 

链接好后可使用cluster nodes命令查看当前集群状态:

127.0.0.1:6379> cluster nodes 4fa7eac4080f0b667ffeab9b87841da49b84a6e4 127.0.0.1:6384 master - 0 1468073975551 5 connected cfb28ef1deee4e0fa78da86abe5d24566744411e 127.0.0.1:6379 myself,master - 0 0 0 connected be9485a6a729fc98c5151374bc30277e89a461d8 127.0.0.1:6383 master - 0 1468073978579 4 connected 40622f9e7adc8ebd77fca0de9edfe691cb8a74fb 127.0.0.1:6382 master - 0 1468073980598 3 connected 8e41673d59c9568aa9d29fb174ce733345b3e8f1 127.0.0.1:6380 master - 0 1468073974541 1 connected 40b8d09d44294d2e23c7c768efc8fcd153446746 127.0.0.1:6381 master - 0 1468073979589 2 connected

能够看到配置的六个节点都已经加入到了集群中,可是其如今还不能使用,由于尚未将16384个槽分配到集群节点中。虚拟槽的分配可使用redis-cli分别链接到6379,6380和6381端口的节点中,而后分别执行以下命令:

127.0.0.1:6379>cluster addslots {0...5461}
127.0.0.1:6380>cluster addslots {5462...10922}
127.0.0.1:6381>cluster addslots {10923...16383}

添加完槽位后可以使用cluster info命令查看当前集群状态:

127.0.0.1:6379> cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:5 cluster_my_epoch:0 cluster_stats_messages_sent:4874 cluster_stats_messages_received:4726 

这里咱们将16384个虚拟槽位分配给了三个节点,而剩余的三个节点咱们经过以下命令将其配置为这三个节点的从节点,从而达到高可用的目的:

127.0.0.1:6382>cluster replicate cfb28ef1deee4e0fa78da86abe5d24566744411e OK 127.0.0.1:6383>cluster replicate 8e41673d59c9568aa9d29fb174ce733345b3e8f1 OK 127.0.0.1:6384>cluster replicate 40b8d09d44294d2e23c7c768efc8fcd153446746 OK 

如此,全部的集群节点都配置完毕,而且处于可用状态。这里可使用cluster nodes命令查看当前节点的状态:

127.0.0.1:6379> cluster nodes 4fa7eac4080f0b667ffeab9b87841da49b84a6e4 127.0.0.1:6384 slave 40b8d09d44294d2e23c7c768efc8fcd153446746 0 1468076865939 5 connected cfb28ef1deee4e0fa78da86abe5d24566744411e 127.0.0.1:6379 myself,master - 0 0 0 connected 0-5461 be9485a6a729fc98c5151374bc30277e89a461d8 127.0.0.1:6383 slave 8e41673d59c9568aa9d29fb174ce733345b3e8f1 0 1468076868966 4 connected 40622f9e7adc8ebd77fca0de9edfe691cb8a74fb 127.0.0.1:6382 slave cfb28ef1deee4e0fa78da86abe5d24566744411e 0 1468076869976 3 connected 8e41673d59c9568aa9d29fb174ce733345b3e8f1 127.0.0.1:6380 master - 0 1468076870987 1 connected 5462-10922 40b8d09d44294d2e23c7c768efc8fcd153446746 127.0.0.1:6381 master - 0 1468076867957 2 connected 10923-16383

咱们使用redis-cli使用以下命令链接集群:

./src/redis-cli -c -p 6380

注意链接集群模式的redis实例时须要加上参数-c,表示链接的是集群模式的实例。链接上后执行get命令:

127.0.0.1:6380> get hello -> Redirected to slot [866] located at 127.0.0.1:6379 (nil)

能够看到,在6380端口的实例上执行get命令时,其首先会为当前的键经过一致哈希算法计算其所在的槽位,而且判断该槽位不在当前redis实例中,于是重定向到目标实例上执行该命令,最后发现没有该键对应的值,于是返回了一个(nil)。

相关文章
相关标签/搜索