Redis集群搭建之Redis Cluster实践
之前一直有用redis,但也一直停留在用的阶段,自己也单机部署过玩玩,但总感觉不深入,所以现在继续研究研究redis集群,下面就根据自己学习实践,记录下使用Redis官网提供的Redis集群方案;
Redis Cluster背景介绍
Redis Cluster与Redis3.0.0同时发布,以此结束了Redis无官方集群方案的时代,目前,Redis已经发布了3.0.7版本。
redis cluster是去中心化,去中间件的,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
那么redis 是如何合理分配这些节点和数据的呢?
Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)的方式来分配的。redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384。
注意的是:必须要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 wind
按照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 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。
上面那个例子里, 集群有ABC三个主节点, 如果这3个节点都没有加入从节点,如果B挂掉了,我们就无法访问整个集群了。A和C的slot也无法访问。
所以我们在集群建立的时候,一定要为每个主节点都添加了从节点, 比如像这样, 集群包含主节点A、B、C, 以及从节点A1、B1、C1, 那么即使B挂掉系统也可以继续正确工作。
B1节点替代了B节点,所以Redis集群将会选择B1节点作为新的主节点,集群将会继续正确地提供服务。 当B重新开启后,它就会变成B1的从节点。
不过需要注意,如果节点B和B1同时挂了,Redis集群就无法继续正确地提供服务了。
redis cluster 动手实践
首先去官方下载Redis,我这里下载的是3.0.5版本。
1.解压
[root@spg redis-claster]# tar -zxvf redis-3.0.5.tar.gz
2.安装
[root@spg redis-claster]#cd redis-3.0.5
[root@spg redis-3.0.5]#make && make install
3.将redis-trib.rb 复制到/usr/local/bin
[root@spg redis-3.0.5]#cp src/redis-trib.rb /usr/local/bin
4.开始集群搭建,首先修改配置文件。
[root@spg redis-3.0.5]#vi redis.conf
修改如下几处:
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
新建6个节点(注意:Redis Cluster要求至少6个节点,3主3备,否则构建集群会报错):
#这里文件名就按端口号命名,方便区分。
[root@spg redis-claster]# mkdir 7000
[root@spg redis-claster]# mkdir 7001
[root@spg redis-claster]# mkdir 7002
[root@spg redis-claster]# mkdir 7003
[root@spg redis-claster]# mkdir 7004
[root@spg redis-claster]# mkdir 7005
将redis.conf 分别拷贝到这6个文件夹中,并修改其中对应的端口号。
分别启动6个Redis。
[root@spg redis-claster]# cd 7000
[root@spg 7000]# redis-server redis.conf &
#其他几个启动略...
可通过查看进程查看各redis是否已经正常启动。
[root@spg redis-claster]# ps -ef | grep redis
root 6568 6127 0 21:50 pts/0 00:00:03 redis-server *:7000 [cluster]
root 6590 6127 0 21:50 pts/0 00:00:02 redis-server *:7001 [cluster]
root 6607 6127 0 21:51 pts/0 00:00:02 redis-server *:7002 [cluster]
root 6613 6127 0 21:51 pts/0 00:00:01 redis-server *:7003 [cluster]
root 6888 6127 0 22:02 pts/0 00:00:00 redis-server *:7004 [cluster]
root 6905 6127 0 22:03 pts/0 00:00:00 redis-server *:7005 [cluster]
接着将6个Redis加入集群。
需要用到的命令就是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,所以,会报错:
[root@spg 7003]# 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/bin/env: ruby: 没有那个文件或目录
通过如下命令安装ruby:
[root@spg 7003]# yum install ruby ruby-devel rubygems rpm-build
完成后继续执行,结果还是报错:
[root@spg 7003]# 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/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- redis (LoadError)
from /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'
from /usr/local/bin/redis-trib.rb:25:in `<main>'
这是因为ruby和redis的连接没安装好:
[root@spg 7003]# gem install redis
Fetching: redis-3.2.2.gem (100%)
Successfully installed redis-3.2.2
Parsing documentation for redis-3.2.2
Installing ri documentation for redis-3.2.2
1 gem installed
安装完后再创建集群。
[root@spg redis-claster]# 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: be26c521481afcd6e739e2bfef69e9dcfb63d0a6 127.0.0.1:7000 slots:0-5460 (5461 slots) master M: ce06b13387702c3ee63e0118dd10c5f81a1285b5 127.0.0.1:7001 slots:5461-10922 (5462 slots) master M: 947cc4a9e890672cfad4806a5921e9f8bdf05c05 127.0.0.1:7002 slots:10923-16383 (5461 slots) master S: 1da8a7f4c3cd5d7537e90e0ca5f4fb416f41a40c 127.0.0.1:7003 replicates be26c521481afcd6e739e2bfef69e9dcfb63d0a6 S: 05ac96f9cdee679f98e8f7ce8e97cf1cbea608ca 127.0.0.1:7004 replicates ce06b13387702c3ee63e0118dd10c5f81a1285b5 S: b65f33d97416795226964aa22f3b4a8ac7366a99 127.0.0.1:7005 replicates 947cc4a9e890672cfad4806a5921e9f8bdf05c05 Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node 6568:M 27 Feb 22:07:57.661 # configEpoch set to 1 via CLUSTER SET-CONFIG-EPOCH 6590:M 27 Feb 22:07:57.661 # configEpoch set to 2 via CLUSTER SET-CONFIG-EPOCH 6607:M 27 Feb 22:07:57.662 # configEpoch set to 3 via CLUSTER SET-CONFIG-EPOCH 6613:M 27 Feb 22:07:57.663 # configEpoch set to 4 via CLUSTER SET-CONFIG-EPOCH 6888:M 27 Feb 22:07:57.664 # configEpoch set to 5 via CLUSTER SET-CONFIG-EPOCH 6905:M 27 Feb 22:07:57.664 # configEpoch set to 6 via CLUSTER SET-CONFIG-EPOCH >>> Sending CLUSTER MEET messages to join the cluster 6568:M 27 Feb 22:07:57.749 # IP address for this node updated to 127.0.0.1 6590:M 27 Feb 22:07:57.751 # IP address for this node updated to 127.0.0.1 6613:M 27 Feb 22:07:57.751 # IP address for this node updated to 127.0.0.1 6607:M 27 Feb 22:07:57.853 # IP address for this node updated to 127.0.0.1 6905:M 27 Feb 22:07:57.853 # IP address for this node updated to 127.0.0.1 6888:M 27 Feb 22:07:57.853 # IP address for this node updated to 127.0.0.1 Waiting for the cluster to join....6568:M 27 Feb 22:08:02.646 # Cluster state changed: ok 6613:S 27 Feb 22:08:02.720 # Cluster state changed: ok 6590:M 27 Feb 22:08:02.722 # Cluster state changed: ok 6888:S 27 Feb 22:08:02.723 # Cluster state changed: ok 6905:S 27 Feb 22:08:02.724 # Cluster state changed: ok >>> Performing Cluster Check (using node 127.0.0.1:7000) 6607:M 27 Feb 22:08:02.747 # Cluster state changed: ok M: be26c521481afcd6e739e2bfef69e9dcfb63d0a6 127.0.0.1:7000 slots:0-5460 (5461 slots) master M: ce06b13387702c3ee63e0118dd10c5f81a1285b5 127.0.0.1:7001 slots:5461-10922 (5462 slots) master M: 947cc4a9e890672cfad4806a5921e9f8bdf05c05 127.0.0.1:7002 slots:10923-16383 (5461 slots) master M: 1da8a7f4c3cd5d7537e90e0ca5f4fb416f41a40c 127.0.0.1:7003 slots: (0 slots) master replicates be26c521481afcd6e739e2bfef69e9dcfb63d0a6 M: 05ac96f9cdee679f98e8f7ce8e97cf1cbea608ca 127.0.0.1:7004 slots: (0 slots) master replicates ce06b13387702c3ee63e0118dd10c5f81a1285b5 M: b65f33d97416795226964aa22f3b4a8ac7366a99 127.0.0.1:7005 slots: (0 slots) master replicates 947cc4a9e890672cfad4806a5921e9f8bdf05c05 [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered.
OK,从上面可看出集群已经创建成果,最后再检查集群各节点状态:
[root@spg redis-3.0.5]# 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:7004: 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:7003: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
M: be26c521481afcd6e739e2bfef69e9dcfb63d0a6 127.0.0.1:7000
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 947cc4a9e890672cfad4806a5921e9f8bdf05c05 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 05ac96f9cdee679f98e8f7ce8e97cf1cbea608ca 127.0.0.1:7004
slots: (0 slots) slave
replicates ce06b13387702c3ee63e0118dd10c5f81a1285b5
S: b65f33d97416795226964aa22f3b4a8ac7366a99 127.0.0.1:7005
slots: (0 slots) slave
replicates 947cc4a9e890672cfad4806a5921e9f8bdf05c05
M: ce06b13387702c3ee63e0118dd10c5f81a1285b5 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 1da8a7f4c3cd5d7537e90e0ca5f4fb416f41a40c 127.0.0.1:7003
slots: (0 slots) slave
replicates be26c521481afcd6e739e2bfef69e9dcfb63d0a6
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
从上面结果可看出集群中6个节点均正常,其中有3个主节点,3个从节点。
5.测试集群链接状况
刚才集群搭建成功了。按照redis cluster的特点,它是去中心化,每个节点都是对等的,所以,你连接哪个节点都可以获取和设置数据,我们来试一下。
redis-cli是redis默认的客户端工具,启动时加上`-c`参数,就可以连接到集群。
连接任意一个节点端口:
[root@spg 7006]# redis-cli -c -p 7003
127.0.0.1:7003>
设置值:
127.0.0.1:7003> set my_name wind
-> Redirected to slot [12803] located at 127.0.0.1:7002
OK
127.0.0.1:7002> get my_name
"wind"
前面说过Redis Cluster值分配规则,所以分配key的时候,它会使用CRC16(‘my_name’)%16384算法,来计算,将这个key 放到哪个节点,这里分配到了12803slot 就分配到了7002(10923-16383)这个节点上。所以有:
Redirected to slot [12803] located at 127.0.0.1:7002
同样,链接其他节点也可获取刚设置的数据,也可以设置其他值测试其key分配。
6.测试集群中某节点宕机情况
上面我们建立来了一个集群。3个主节点[7000-7002]提供数据存储和读取,3个从节点[7003-7005]则是负责把[7000-7002]的数据同步到自己的节点上来,我们来看一下[7003-7005]的appendonly.aof的内容,验证是不是说的这样,我们看7005节点数据:
[root@spg 7005]# vim appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$7
my_name
$4
wind
我们看下,的确是从7000节点上同步过来的数据,7003,7004也是。
下面,我们先来模拟其中一台Master主服务器挂掉的情况,那就7000挂掉吧:
[root@spg 7005]# ps -ef | grep redis
root 3027 2974 0 20:03 pts/0 00:00:04 redis-server *:7000 [cluster]
root 3063 2974 0 20:04 pts/0 00:00:03 redis-server *:7001 [cluster]
root 3081 2974 0 20:05 pts/0 00:00:03 redis-server *:7002 [cluster]
root 3093 2974 0 20:05 pts/0 00:00:03 redis-server *:7003 [cluster]
root 3109 2974 0 20:06 pts/0 00:00:02 redis-server *:7004 [cluster]
root 3123 2974 0 20:06 pts/0 00:00:02 redis-server *:7005 [cluster]
root 3406 2974 0 20:23 pts/0 00:00:00 grep --color=auto redis
[root@spg 7005]# kill -9 3027
好,按照前面的理论,7000主节点挂掉了,那么这个时候,7000的从节点只有7003一个,肯定7003就会被选举称Master节点了:
[root@spg 7005]# 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:7005: 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
>>> Performing Cluster Check (using node 127.0.0.1:7001)
M: ce06b13387702c3ee63e0118dd10c5f81a1285b5 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: b65f33d97416795226964aa22f3b4a8ac7366a99 127.0.0.1:7005
slots: (0 slots) slave
replicates 947cc4a9e890672cfad4806a5921e9f8bdf05c05
M: 947cc4a9e890672cfad4806a5921e9f8bdf05c05 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
M: 1da8a7f4c3cd5d7537e90e0ca5f4fb416f41a40c 127.0.0.1:7003
slots:0-5460 (5461 slots) master
0 additional replica(s)
S: 05ac96f9cdee679f98e8f7ce8e97cf1cbea608ca 127.0.0.1:7004
slots: (0 slots) slave
replicates ce06b13387702c3ee63e0118dd10c5f81a1285b5
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
看了下,上面有了三个M 节点了,果真,7003被选取成了替代7000成为主节点了。如果前面在7000节点上存有数据,此时连接redis,7000节点上数据依然可正常获取,因为数据已经同步到其备机7003上。
OK。我们再来模拟 7000节点重新启动了的情况,那么它还会自动加入到集群中吗?那么,7000这个节点上充当什么角色呢? 我们试一下:
[root@spg 7005]# cd ../7000
[root@spg 7000]# redis-server redis.conf &
启动完成后再验证集群状态,同时查看集群中7000角色
[root@spg 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:7003: 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:7001: OK
Connecting to node 127.0.0.1:7005: OK
>>> Performing Cluster Check (using node 127.0.0.1:7000)
S: be26c521481afcd6e739e2bfef69e9dcfb63d0a6 127.0.0.1:7000
slots: (0 slots) slave
replicates 1da8a7f4c3cd5d7537e90e0ca5f4fb416f41a40c
M: 1da8a7f4c3cd5d7537e90e0ca5f4fb416f41a40c 127.0.0.1:7003
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 947cc4a9e890672cfad4806a5921e9f8bdf05c05 127.0.0.1:7002
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 05ac96f9cdee679f98e8f7ce8e97cf1cbea608ca 127.0.0.1:7004
slots: (0 slots) slave
replicates ce06b13387702c3ee63e0118dd10c5f81a1285b5
M: ce06b13387702c3ee63e0118dd10c5f81a1285b5 127.0.0.1:7001
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: b65f33d97416795226964aa22f3b4a8ac7366a99 127.0.0.1:7005
slots: (0 slots) slave
replicates 947cc4a9e890672cfad4806a5921e9f8bdf05c05
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
由上面可知7000已经正常,但是作为了7003的备机存在。
总结:至此,基于Redis官网的Redis Cluster解决方案,完成了Redis集群的搭建,过程稍微复杂,但相信熟练起来就会很顺手,后面会继续实践集群中节点的增减情况。
参考:
https://www.zybuluo.com/phper/note/195558
http://redisdoc.com/topic/cluster-tutorial.html
还没有评论,来说两句吧...