一. 集群简单概念。
Redis 集群是一组能进行数据共享的Redis 实例(服务或者节点)的设施,集群可以使用的功能是普通单机 Redis 所能使用的功能的一个子集;Redis 集群通常具有高可用、可扩展性、分布式、容错等特性。了解redis的集群后,这些晦涩的概念可结合redis的主从、集群分区和集群运维等角度理解体会。
Redis 集群是一个可以
在多个 Redis 节点之间进行数据共享的设施(installation)。
Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令需要在多个 Redis 节点之间移动数据, 并且在高负载的情况下, 这些命令将降低 Redis 集群的性能, 并导致不可预测的行为。
Redis 集群
通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。
Redis 集群提供了以下两个好处:
- 将数据自动切分(split)到多个节点的能力。
- 当集群中的一部分节点失效或者无法进行通讯时, 仍然可以继续处理命令请求的能力。
Redis 集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现: 一个 Redis 集群包含
16384
个哈希槽(hash slot), 数据库中的每个键都属于这
16384
个哈希槽的其中一个, 集群使用公式
CRC16(key)
%
16384
来计算键
key
属于哪个槽, 其中
CRC16(key)
语句用于计算键
key
的
CRC16 校验和
。
集群中的每个节点负责处理一部分哈希槽。 举个例子, 一个集群可以有三个哈希槽, 其中:
- 节点 A 负责处理
0
号至
5500
号哈希槽。
- 节点 B 负责处理
5501
号至
11000
号哈希槽。
- 节点 C 负责处理
11001
号至
16384
号哈希槽。
这种将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点。 比如说:
- 如果用户将新节点 D 添加到集群中, 那么集群只需要将节点 A 、B 、 C 中的某些槽移动到节点 D 就可以了。
- 与此类似, 如果用户要从集群中移除节点 A , 那么集群只需要将节点 A 中的所有哈希槽移动到节点 B 和节点 C , 然后再移除空白(不包含任何哈希槽)的节点 A 就可以了。
因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线。
为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下, 仍然可以正常运作, Redis 集群对节点使用了主从复制功能: 集群中的每个节点都有
1
个至
N
个复制品(replica), 其中一个复制品为主节点(master), 而其余的
N-1
个复制品为从节点(slave)。
在之前列举的节点 A 、B 、C 的例子中, 如果节点 B 下线了, 那么集群将无法正常运行, 因为集群找不到节点来处理
5501
号至
11000号的哈希槽。
另一方面, 假如在创建集群的时候(或者至少在节点 B 下线之前), 我们为主节点 B 添加了从节点 B1 , 那么当主节点 B 下线的时候, 集群就会将 B1 设置为新的主节点, 并让它代替下线的主节点 B , 继续处理
5501
号至
11000
号的哈希槽, 这样集群就不会因为主节点 B 的下线而无法正常运作了。
不过如果节点 B 和 B1 都下线的话, Redis 集群还是会停止运作。
Redis-cluster 架构图如下:
架构细节:
(1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽.
(2)节点的fail是通过集群中超过半数的节点检测失效时才生效.
(3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
(4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value
二. Redis Cluster搭建使用
要让集群正常工作至少需要3个主节点,在这里我们要创建6个redis节点,其中三个为主节点,三个为从节点,对应的redis节点的ip和端口对应关系如下(为了简单演示都在同一台机器上面)
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
-
下载最新版redis。
1
2 1wget http://download.redis.io/releases/redis-3.0.0.tar.gz
2
下载到当前目录, 可以移动到指定目录
mv -t /usr/local redis-3.0.0
-
解压,安装
1
2
3
4 1tar xf redis-3.0.0.tar.gz
2cd redis-3.0.0
3make && make install
4
可能会有两种错误
a。未安装gcc命令 yum install -y gcc automake autoconf libtool make
b。解决方法:
make MALLOC=libc
1
2
3
4
5
6
7
8
9
10
11 1[root@localhost redis-3.2.0]# make
2cd src && make all
3make[1]: Entering directory `/opt/redis-3.2.0/src'
4 CC adlist.o
5在包含自 adlist.c:34 的文件中:
6zmalloc.h:50:31: 错误:jemalloc/jemalloc.h:没有那个文件或目录
7zmalloc.h:55:2: 错误:#error "Newer version of jemalloc required"
8make[1]: *** [adlist.o] 错误 1
9make[1]: Leaving directory `/opt/redis-3.2.0/src'
10make: *** [all] 错误 2
11
3.创建存放多个实例的目录
1
2
3
4 1mkdir /data/cluster -p
2cd /data/cluster
3mkdir 7000 7001 7002 7003 7004 7005
4
4.修改配置文件
1
2 1cp redis-3.0.0/redis.conf /data/cluster/7000/
2
修改配置文件中下面选项
port 7000
daemonize yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
文件中的
cluster-enabled
选项用于开实例的集群模式, 而
cluster-conf-file
选项则设定了保存节点配置文件的路径, 默认值为
nodes.conf
。其他参数相信童鞋们都知道。节点配置文件无须人为修改, 它由 Redis 集群在启动时创建, 并在有需要时自动进行更新。
修改完成后,把修改完成的redis.conf复制到7001-7005目录下,并且端口修改成和文件夹对应。
5.分别启动6个redis实例。
1
2
3
4
5
6
7
8
9
10
11
12
13 1cd /data/cluster/7000
2redis-server redis.conf
3cd /data/cluster/7001
4redis-server redis.conf
5cd /data/cluster/7002
6redis-server redis.conf
7cd /data/cluster/7003
8redis-server redis.conf
9cd /data/cluster/7004
10redis-server redis.conf
11cd /data/cluster/7005
12redis-server redis.conf
13
查看进程否存在。
1
2
3
4
5
6
7
8
9 1[root@redis-server 7005]# ps -ef | grep redis
2root 4168 1 0 11:49 ? 00:00:00 redis-server *:7000 [cluster]
3root 4176 1 0 11:49 ? 00:00:00 redis-server *:7001 [cluster]
4root 4186 1 0 11:50 ? 00:00:00 redis-server *:7002 [cluster]
5root 4194 1 0 11:50 ? 00:00:00 redis-server *:7003 [cluster]
6root 4202 1 0 11:50 ? 00:00:00 redis-server *:7004 [cluster]
7root 4210 1 0 11:50 ? 00:00:00 redis-server *:7005 [cluster]
8root 4219 4075 0 11:50 pts/2 00:00:00 grep redis
9
6.执行命令创建集群,首先安装依赖,否则创建集群失败。
1
2 1yum install ruby rubygems -y
2
安装gem-redis
下载地址:https://rubygems.org/gems/redis/versions/3.0.0
1
2 1gem install -l redis-3.0.0.gem
2
复制集群管理程序到/usr/local/bin
1
2 1cp redis-3.0.0/src/redis-trib.rb /usr/local/bin/redis-trib
2
创建集群:
1
2 1redis-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
2
命令的意义如下:
- 给定
redis-trib.rb
程序的命令是
create
, 这表示我们希望创建一个新的集群。
- 选项
–replicas
1
表示我们希望为集群中的每个主节点创建一个从节点。
- 之后跟着的其他参数则是实例的地址列表, 我们希望程序使用这些地址所指示的实例来创建新集群。
简单来说, 以上命令的意思就是让
redis-trib
程序创建一个包含三个主节点和三个从节点的集群。
接着,
redis-trib
会打印出一份预想中的配置给你看, 如果你觉得没问题的话, 就可以输入
yes
,
redis-trib
就会将这份配置应用到集群当中:
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 1>>> Creating cluster
2Connecting to node 127.0.0.1:7000: OK
3Connecting to node 127.0.0.1:7001: OK
4Connecting to node 127.0.0.1:7002: OK
5Connecting to node 127.0.0.1:7003: OK
6Connecting to node 127.0.0.1:7004: OK
7Connecting to node 127.0.0.1:7005: OK
8>>> Performing hash slots allocation on 6 nodes...
9Using 3 masters:
10127.0.0.1:7000
11127.0.0.1:7001
12127.0.0.1:7002
13Adding replica 127.0.0.1:7003 to 127.0.0.1:7000
14Adding replica 127.0.0.1:7004 to 127.0.0.1:7001
15Adding replica 127.0.0.1:7005 to 127.0.0.1:7002
16M: 2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000
17 slots:0-5460 (5461 slots) master
18M: 2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001
19 slots:5461-10922 (5462 slots) master
20M: 0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002
21 slots:10923-16383 (5461 slots) master
22S: 37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003
23 replicates 2774f156af482b4f76a5c0bda8ec561a8a1719c2
24S: e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004
25 replicates 2d03b862083ee1b1785dba5db2987739cf3a80eb
26S: 9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005
27 replicates 0456869a2c2359c3e06e065a09de86df2e3135ac
28Can I set the above configuration? (type 'yes' to accept):
29
输入
yes
并按下回车确认之后, 集群就会将配置应用到各个节点, 并连接起(join)各个节点 —— 也即是, 让各个节点开始互相通讯:
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 1Can I set the above configuration? (type 'yes' to accept): yes
2>>> Nodes configuration updated
3>>> Assign a different config epoch to each node
4>>> Sending CLUSTER MEET messages to join the cluster
5Waiting for the cluster to join......
6>>> Performing Cluster Check (using node 127.0.0.1:7000)
7M: 2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000
8 slots:0-5460 (5461 slots) master
9M: 2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001
10 slots:5461-10922 (5462 slots) master
11M: 0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002
12 slots:10923-16383 (5461 slots) master
13M: 37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003
14 slots: (0 slots) master
15 replicates 2774f156af482b4f76a5c0bda8ec561a8a1719c2
16M: e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004
17 slots: (0 slots) master
18 replicates 2d03b862083ee1b1785dba5db2987739cf3a80eb
19M: 9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005
20 slots: (0 slots) master
21 replicates 0456869a2c2359c3e06e065a09de86df2e3135ac
22[OK] All nodes agree about slots configuration.
23>>> Check for open slots...
24>>> Check slots coverage...
25[OK] All 16384 slots covered.
26
一切正常输出以下信息:
1
2
3
4
5 1[OK] All nodes agree about slots configuration.
2>>> Check for open slots...
3>>> Check slots coverage...
4[OK] All 16384 slots covered.
5
集群的客户端
Redis 集群现阶段的一个问题是客户端实现很少。 以下是一些我知道的实现:
- redis-rb-cluster
是我(@antirez)编写的 Ruby 实现, 用于作为其他实现的参考。 该实现是对
redis-rb
的一个简单包装, 高效地实现了与集群进行通讯所需的最少语义(semantic)。
- redis-py-cluster
看上去是
redis-rb-cluster
的一个 Python 版本, 这个项目有一段时间没有更新了(最后一次提交是在六个月之前), 不过可以将这个项目用作学习集群的起点。
- 流行的 Predis 曾经对早期的 Redis 集群有过一定的支持, 但我不确定它对集群的支持是否完整, 也不清楚它是否和最新版本的 Redis 集群兼容 (因为新版的 Redis 集群将槽的数量从 4k 改为 16k 了)。
- Redis
unstable
分支中的
redis-cli
程序实现了非常基本的集群支持, 可以使用命令
redis-cli
-c
来启动。
测试 Redis 集群比较简单的办法就是使用
redis-rb-cluster
或者
redis-cli
, 接下来我们将使用
redis-cli
为例来进行演示:
1
2
3
4
5
6
7 1[root@redis-server ~]# redis-cli -c -p 7001
2127.0.0.1:7001> set name yayun
3OK
4127.0.0.1:7001> get name
5"yayun"
6127.0.0.1:7001>
7
我们可以看看还有哪些命令可以用:
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 1[root@redis-server ~]# redis-trib help
2Usage: redis-trib <command> <options> <arguments ...>
3
4 set-timeout host:port milliseconds
5 add-node new_host:new_port existing_host:existing_port
6 --master-id <arg>
7 --slave
8 fix host:port
9 help (show this help)
10 del-node host:port node_id
11 import host:port
12 --from <arg>
13 check host:port
14 call host:port command arg arg .. arg
15 create host1:port1 ... hostN:portN
16 --replicas <arg>
17 reshard host:port
18 --yes
19 --to <arg>
20 --from <arg>
21 --slots <arg>
22
23For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
24[root@redis-server ~]#
25
可以看见有add-node,不用想了,肯定是添加节点。那么del-node就是删除节点。还有check肯定就是检查状态了。
1
2
3
4
5
6
7
8
9 1[root@redis-server ~]# redis-cli -p 7000 cluster nodes
22d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001 master - 0 1428293673322 2 connected 5461-10922
337b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003 slave 2774f156af482b4f76a5c0bda8ec561a8a1719c2 0 1428293672305 4 connected
4e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004 slave 2d03b862083ee1b1785dba5db2987739cf3a80eb 0 1428293674340 5 connected
50456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002 master - 0 1428293670262 3 connected 10923-16383
62774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000 myself,master - 0 0 1 connected 0-5460
79923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005 slave 0456869a2c2359c3e06e065a09de86df2e3135ac 0 1428293675362 6 connected
8[root@redis-server ~]#
9
可以看到7000-7002是master,7003-7005是slave。
故障转移测试:
1
2
3
4
5
6 1127.0.0.1:7001> KEYS *
21) "name"
3127.0.0.1:7001> get name
4"yayun"
5127.0.0.1:7001>
6
可以看见7001是正常的,并且获取到了key,value,现在kill掉7000实例,再进行查询。
1
2
3
4
5
6
7
8
9
10
11 1[root@redis-server ~]# ps -ef | grep 7000
2root 4168 1 0 11:49 ? 00:00:03 redis-server *:7000 [cluster]
3root 4385 4361 0 12:39 pts/3 00:00:00 grep 7000
4[root@redis-server ~]# kill 4168
5[root@redis-server ~]# ps -ef | grep 7000
6root 4387 4361 0 12:39 pts/3 00:00:00 grep 7000
7[root@redis-server ~]# redis-cli -c -p 7001
8127.0.0.1:7001> get name
9"yayun"
10127.0.0.1:7001>
11
可以正常获取到value,现在看看状态。
1
2
3
4
5
6
7
8
9 1[root@redis-server ~]# redis-cli -c -p 7001 cluster nodes
22d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001 myself,master - 0 0 2 connected 5461-10922
30456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002 master - 0 1428295271619 3 connected 10923-16383
437b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003 master - 0 1428295270603 7 connected 0-5460
5e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004 slave 2d03b862083ee1b1785dba5db2987739cf3a80eb 0 1428295272642 5 connected
62774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000 master,fail - 1428295159553 1428295157205 1disconnected
79923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005 slave 0456869a2c2359c3e06e065a09de86df2e3135ac 0 1428295269587 6 connected
8[root@redis-server ~]#
9
原来的7000端口实例已经显示fail,原来的7003是slave,现在自动提升为master。
关于更多的在线添加节点,删除节点,以及对集群进行重新分片请参考官方文档。
关闭redis集群和启动注意:一个一个关闭
for((i=0;i<=5;i++)); do /usr/local/bin/redis-cli -c -h 127.0.0.1 -p 700$i shutdown; done;
还要删除redis的临时文件:
for((i=0;i<=5;i++)); do cd /usr/local/redis-cluster/700$i; rm -rf appendonly.aof; rm -rf dump.rdb; rm -rf nodes.conf; cd ..; done;
启动时,每个redis实例需要单独启动, 启动完成后可用启动集群命令:
1
2 1redis-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
2
Redis集群分区原理
槽(slot)的基本概念
从上面集群的简单操作中,我们已经知道redis存取key的时候,都要定位相应的槽(slot)。
Redis 集群键分布算法使用数据分片(sharding)而非一致性哈希(consistency hashing)
来实现:
一个 Redis 集群包含 16384 个哈希槽(hash slot)
, 它们的编号为0、1、2、3……16382、16383,这个槽是一个逻辑意义上的槽,实际上并不存在。redis中的每个key都属于这 16384 个哈希槽的其中一个,存取key时都要进行key->slot的映射计算。
下面我们来看看启动集群时候打印的信息:
Creating cluster
Performing hash slots allocation on 6 nodes…
Using 3 masters:
192.168.2.128:7031
192.168.2.128:7032
192.168.2.128:7033
Adding replica 192.168.2.128:7034 to 192.168.2.128:7031
Adding replica 192.168.2.128:7035 to 192.168.2.128:7032
Adding replica 192.168.2.128:7036 to 192.168.2.128:7033
M: bee706db5ae182c5be9b9bdf94c2d6f3f8c8ec5c 192.168.2.128:7031
slots:0-5460 (5461 slots) master
M: 72826f06dbf3be163f2f456ca24caed76a15bdf4 192.168.2.128:7032
slots:5461-10922 (5462 slots) master
M: ab6e9d1dfc471225eef01e57be563157f81d26b3 192.168.2.128:7033
slots:10923-16383 (5461 slots) master
……
[OK] All nodes agree about slots configuration.
Check for open slots…
Check slots coverage…
[OK] All 16384 slots covered.
从上面信息可以看出,创建集群的时候,
哈希槽被分配到了三个主节点上,从节点是没有哈希槽的
。7031负责编号为0-5460 共5461个 slots,7032负责编号为
5461-10922共5462 个 slots,7033负责编号为10923-16383 共5461个 slots。
键-槽映射算法
和memcached一样,redis也采用一定的算法进行键-槽(key->slot)之间的映射。memcached采用一致性哈希(consistency hashing)算法进行键-节点(key-node)之间的映射,而redis集群使用集群公式来计算键 key 属于哪个槽:
HASH_SLOT(key)= CRC16(key) % 16384
其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。key经过公式计算后得到所对应的哈希槽,而哈希槽被某个主节点管理,从而确定key在哪个主节点上存取,这也是redis将数据均匀分布到各个节点上的基础。
键-槽-节点(key->slot->node)映射示意图
集群分区好处
无论是memcached的一致性哈希算法,还是redis的集群分区,最主要的
目的都是在移除、添加一个节点时对已经存在的缓存数据的定位影响尽可能的降到最小
。redis将哈希槽分布到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点, 比如说:
l 如果用户将新节点 D 添加到集群中, 那么集群只需要将节点 A 、B 、 C 中的某些槽移动到节点 D 就可以了。
l 与此类似, 如果用户要从集群中移除节点 A , 那么集群只需要将节点 A 中的所有哈希槽移动到节点 B 和节点 C , 然后再移除空白(不包含任何哈希槽)的节点 A 就可以了。
因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞, 所以无论是添加新节点还是移除已存在节点, 又或者改变某个节点包含的哈希槽数量, 都不会造成集群下线,从而保证集群的可用性。下面我们就来学习下集群中节点的增加和删除。
集群操作
集群操作包括查看集群信息,查看集群节点信息,向集群中增加节点、删除节点,重新分配槽等操作。
查看集群信息
cluster info 查看集群状态,槽分配,集群大小等,cluster nodes也可查看主从节点。
192.168.2.128:7031> 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:6
cluster_my_epoch:1
cluster_stats_messages_sent:119
cluster_stats_messages_received:119
192.168.2.128:7031>
新增节点
(1)新增节点配置文件
执行下面的脚本创建脚本配置文件
[root@localhost redis-cluster]# mkdir /usr/local/redis-cluster/7037 && cp /usr/local/redis-cluster/7031/redis.conf /usr/local/redis-cluster/7037/redis.conf && sed -i "s/7031/7037/g" /usr/local/redis-cluster/7037/redis.conf
(2)启动新增节点
[root@localhost bin]# /usr/local/redis/bin/redis-server /usr/local/redis-cluster/7037/redis.conf
(3)添加节点到集群
现在已经添加了新增一个节点所需的配置文件,但是这个这点还没有添加到集群中,现在让它成为集群中的一个主节点
[root@localhost redis-cluster]# cd /usr/local/redis/bin/
[root@localhost bin]#
./redis-trib.rb add-node 192.168.2.128:7037 192.168.2.128:7036
Adding node 192.168.2.128:7037 to cluster 192.168.2.128:7036
Performing Cluster Check (using node 192.168.2.128:7036)
S: 2c8d72f1914f9d6052065f7e9910cc675c3c717b 192.168.2.128:7036
slots: (0 slots) slave
replicates 6dbb4aa323864265c9507cf336ef7d3b95ea8d1b
M: 6dbb4aa323864265c9507cf336ef7d3b95ea8d1b 192.168.2.128:7033
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 791a7924709bfd7ef5c36d9b9c838925e41e3c2e 192.168.2.128:7034
slots: (0 slots) slave
replicates d9e3c78a7c49689c29ab67a8a17be9d95cb08452
M: d9e3c78a7c49689c29ab67a8a17be9d95cb08452 192.168.2.128:7031
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 69b63d8db629fa8a689dd1ed25ed941c076d4111 192.168.2.128:7032
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: e669a91866225279aafcac29bf07b826eb5be91c 192.168.2.128:7035
slots: (0 slots) slave
replicates 69b63d8db629fa8a689dd1ed25ed941c076d4111
[OK] All nodes agree about slots configuration.
Check for open slots…
Check slots coverage…
[OK] All 16384 slots covered.
Send CLUSTER MEET to node 192.168.2.128:7037 to make it join the cluster.
[OK] New node added correctly.
[root@localhost bin]#
./redis-trib.rb add-node 命令中,7037 是新增的主节点,7036 是集群中已有的从节点。再来看看集群信息
192.168.2.128:7031> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:7
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_sent:11256
cluster_stats_messages_received:11256
(4)分配槽
从添加主节点输出信息和查看集群信息中可以看出,我们已经成功的向集群中添加了一个主节点,但是这个主节还没有成为真正的主节点,因为还没有分配槽(slot),也没有从节点,现在要给它分配槽(slot)
[root@localhost bin]#
./redis-trib.rb reshard 192.168.2.128:7031
Performing Cluster Check (using node 192.168.2.128:7031)
M: 1a544a9884e0b3b9a73db80633621bd90ceff64a 192.168.2.128:7031
……
[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)? 1024
What is the receiving node ID?
系统提示要移动多少个配槽(slot),并且配槽(slot)要移动到哪个节点,任意输入一个数,如1024,再输入新增节点的ID cf48228259def4e51e7e74448e05b7a6c8f5713f.
What is the receiving node ID? cf48228259def4e51e7e74448e05b7a6c8f5713f
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:
然后提示要从哪几个节点中移除1024个槽(slot),这里输入‘all’表示从所有的主节点中随机转移,凑够1024个哈希槽,然后就开始从新分配槽(slot)了。从新分配完后再次查看集群节点信息
可见,0-340 5461-5802 10923-11263的槽(slot)被分配给了新增加的节点。三个加起来刚好1024个槽(slot)。
(5)指定从节点
现在从节点7036的主节点是7033,现在我们要把他变为新增加节点(7037)的从节点,需要登录7036的客户端
[root@localhost bin]# /usr/local/redis/bin/redis-cli -c -h 192.168.2.128 -p 7036
192.168.2.128:7036> cluster replicate cf48228259def4e51e7e74448e05b7a6c8f5713f
OK
再来查看集群节点信息
可见,7036成为了新增节点7037的从节点。
删除节点
指定删除节点的ID即可,如下
[root@localhost bin]#
./redis-trib.rb del-node 192.168.2.128:7037 'a56461a171334560f16652408c2a45e629d268f6'
Removing node a56461a171334560f16652408c2a45e629d268f6 from cluster 192.168.2.128:7037
Sending CLUSTER FORGET messages to the cluster…
SHUTDOWN the node.
[root@localhost bin]#
集群操作小结
从上面过程可以看出,
添加节点、分配槽、删除节点的过程,不用停止集群,不阻塞集群的其他操作
。命令小结
#向集群中添加节点,7037是新增节点,7036是集群中已有的节点
./redis-trib.rb add-node 192.168.2.128:7037 192.168.2.128:7036
#重新分配槽
./redis-trib.rb reshard 192.168.2.128:7031
#指定当前节点的主节点
cluster replicate cf48228259def4e51e7e74448e05b7a6c8f5713f
#删除节点
./redis-trib.rb del-node 192.168.2.128:7037 'a56461a171334560f16652408c2a45e629d268f6'
到此,redis的集群搭建、分区原理、集群增加节点以及删除节点的主要内容已经简要介绍完毕。