Redis Cluster终于出了Stable,这让人很是激动,等Stable很久了,所以还是先玩玩。
Redis Cluster基本概念
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
1. 下载最新版redis
- wget http://download.redis.io/releases/redis-3.0.0.tar.gz
2. 解压,安装
- tar xf redis-3.0.0.tar.gz
- cd redis-3.0.0
- make && make install
3.创建存放多个实例的目录
- mkdir /data/cluster -p
- cd /data/cluster
- mkdir 7000 7001 7002 7003 7004 7005
4.修改配置文件
- cp redis-3.0.0/redis.conf /data/cluster/7000/
修改配置文件中下面选项
- 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实例
- cd /data/cluster/7000
- redis-server redis.conf
- cd /data/cluster/7001
- redis-server redis.conf
- cd /data/cluster/7002
- redis-server redis.conf
- cd /data/cluster/7003
- redis-server redis.conf
- cd /data/cluster/7004
- redis-server redis.conf
- cd /data/cluster/7005
- redis-server redis.conf
查看进程否存在。
- [root@redis-server 7005]# ps -ef | grep redis
- root 4168 1 0 11:49 ? 00:00:00 redis-server *:7000 [cluster]
- root 4176 1 0 11:49 ? 00:00:00 redis-server *:7001 [cluster]
- root 4186 1 0 11:50 ? 00:00:00 redis-server *:7002 [cluster]
- root 4194 1 0 11:50 ? 00:00:00 redis-server *:7003 [cluster]
- root 4202 1 0 11:50 ? 00:00:00 redis-server *:7004 [cluster]
- root 4210 1 0 11:50 ? 00:00:00 redis-server *:7005 [cluster]
- root 4219 4075 0 11:50 pts/2 00:00:00 grep redis
6.执行命令创建集群
首先安装依赖,否则创建集群失败。
- yum install ruby rubygems -y
安装gem-redis
下载地址:https://rubygems.org/gems/redis/versions/3.0.0
- gem install redis -v 3.0.0
复制集群管理程序到/usr/local/bin
- cp redis-3.0.0/src/redis-trib.rb /usr/local/bin/redis-trib
创建集群:
- redis-trib 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
命令的意义如下:
- 给定 redis-trib.rb 程序的命令是 create , 这表示我们希望创建一个新的集群。
- 选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
- 之后跟着的其他参数则是实例的地址列表, 我们希望程序使用这些地址所指示的实例来创建新集群。
简单来说, 以上命令的意思就是让 redis-trib 程序创建一个包含三个主节点和三个从节点的集群。
接着, redis-trib 会打印出一份预想中的配置给你看, 如果你觉得没问题的话, 就可以输入 yes , redis-trib 就会将这份配置应用到集群当中:
- >>> 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: 2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000
- slots:0-5460 (5461 slots) master
- M: 2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001
- slots:5461-10922 (5462 slots) master
- M: 0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002
- slots:10923-16383 (5461 slots) master
- S: 37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003
- replicates 2774f156af482b4f76a5c0bda8ec561a8a1719c2
- S: e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004
- replicates 2d03b862083ee1b1785dba5db2987739cf3a80eb
- S: 9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005
- replicates 0456869a2c2359c3e06e065a09de86df2e3135ac
- Can I set the above configuration? (type 'yes' to accept):
输入 yes 并按下回车确认之后, 集群就会将配置应用到各个节点, 并连接起(join)各个节点 —— 也即是, 让各个节点开始互相通讯:
- 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: 2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000
- slots:0-5460 (5461 slots) master
- M: 2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001
- slots:5461-10922 (5462 slots) master
- M: 0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002
- slots:10923-16383 (5461 slots) master
- M: 37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003
- slots: (0 slots) master
- replicates 2774f156af482b4f76a5c0bda8ec561a8a1719c2
- M: e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004
- slots: (0 slots) master
- replicates 2d03b862083ee1b1785dba5db2987739cf3a80eb
- M: 9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005
- slots: (0 slots) master
- replicates 0456869a2c2359c3e06e065a09de86df2e3135ac
- [OK] All nodes agree about slots configuration.
- >>> Check for open slots...
- >>> Check slots coverage...
- [OK] All 16384 slots covered.
一切正常输出以下信息:
- [OK] All nodes agree about slots configuration.
- >>> Check for open slots...
- >>> Check slots coverage...
- [OK] All 16384 slots covered.
Redis Cluster客户端
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 Cluster测试
集群比较简单的办法就是使用 redis-rb-cluster 或者 redis-cli , 接下来我们将使用 redis-cli 为例来进行演示:
redis-cli基本测试
- [root@redis-server ~]# redis-cli -c -p 7001
- 127.0.0.1:7001> set name yayun
- OK
- 127.0.0.1:7001> get name
- "yayun"
- 127.0.0.1:7001>
我们可以看看还有哪些命令可以用:
- [root@redis-server ~]# redis-trib help
- Usage: redis-trib <command> <options> <arguments ...>
-
- set-timeout host:port milliseconds
- add-node new_host:new_port existing_host:existing_port
- --master-id <arg>
- --slave
- fix host:port
- help (show this help)
- del-node host:port node_id
- import host:port
- --from <arg>
- check host:port
- call host:port command arg arg .. arg
- create host1:port1 ... hostN:portN
- --replicas <arg>
- reshard host:port
- --yes
- --to <arg>
- --from <arg>
- --slots <arg>
-
- For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster.
- [root@redis-server ~]#
可以看见有add-node,不用想了,肯定是添加节点。那么del-node就是删除节点。还有check肯定就是检查状态了。
状态检查 cluster nodes
- [root@redis-server ~]# redis-cli -p 7000 cluster nodes
- 2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001 master - 0 1428293673322 2 connected 5461-10922
- 37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003 slave 2774f156af482b4f76a5c0bda8ec561a8a1719c2 0 1428293672305 4 connected
- e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004 slave 2d03b862083ee1b1785dba5db2987739cf3a80eb 0 1428293674340 5 connected
- 0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002 master - 0 1428293670262 3 connected 10923-16383
- 2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000 myself,master - 0 0 1 connected 0-5460
- 9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005 slave 0456869a2c2359c3e06e065a09de86df2e3135ac 0 1428293675362 6 connected
- [root@redis-server ~]#
检查集群,我们通过check cluster的一个节点,就知道整个集群的状况,可以看出来哪些节点是主,哪些是从。由上可以看到7000-7002是master,7003-7005是slave。
删除节点 del node
- [root@redis-cluster-yang 7001]# redis-trib del-node 127.0.0.1:7001 '518a8abc4a64578a51323492a8c79c29a1354f4f'
- >>> Removing node 518a8abc4a64578a51323492a8c79c29a1354f4f from cluster 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:7000: 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
- >>> Sending CLUSTER FORGET messages to the cluster...
- >>> SHUTDOWN the node.
- [root@redis-cluster-yang 7001]# redis-trib check 127.0.0.1:7000
- Connecting to node 127.0.0.1:7000: 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:7004: OK
- Connecting to node 127.0.0.1:7002: OK
- >>> Performing Cluster Check (using node 127.0.0.1:7000)
- M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000
- slots:0-5460 (5461 slots) master
- 1 additional replica(s)
- S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005
- slots: (0 slots) slave
- replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62
- S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003
- slots: (0 slots) slave
- replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7
- M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004
- slots:5461-10922 (5462 slots) master
- 0 additional replica(s)
- M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 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.
添加节点add-node
- [root@redis-cluster-yang 7001]# redis-trib check 127.0.0.1:7004
- 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:7004)
- M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004
- slots:5461-10922 (5462 slots) master
- 0 additional replica(s)
- M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000
- slots:0-5460 (5461 slots) master
- 1 additional replica(s)
- M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 127.0.0.1:7002
- slots:10923-16383 (5461 slots) master
- 1 additional replica(s)
- S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005
- slots: (0 slots) slave
- replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62
- S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003
- slots: (0 slots) slave
- replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7
- [OK] All nodes agree about slots configuration.
- >>> Check for open slots...
- >>> Check slots coverage...
- [OK] All 16384 slots covered.
- [root@redis-cluster-yang 7001]# redis-trib add-node 127.0.0.1:7001 127.0.0.1:7004
- >>> Adding node 127.0.0.1:7001 to cluster 127.0.0.1:7004
- 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:7004)
- M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004
- slots:5461-10922 (5462 slots) master
- 0 additional replica(s)
- M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000
- slots:0-5460 (5461 slots) master
- 1 additional replica(s)
- M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 127.0.0.1:7002
- slots:10923-16383 (5461 slots) master
- 1 additional replica(s)
- S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005
- slots: (0 slots) slave
- replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62
- S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003
- slots: (0 slots) slave
- replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7
- [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:7001: OK
- [ERR] Node 127.0.0.1:7001 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
最常见的错误是Node 127.0.0.1:7001 is not empty。解决办法亦很简单。需要删除redis.conf里面cluster-config-file所指定的文件。然后通过redis-cli -p port进去,使用flushall命令删掉所有的数据…… 这两件事情都做OK了,重新启动redis,再执行添加节点操作就不会提示 not empty了。
- [root@redis-cluster-yang 7001]# redis-trib add-node 127.0.0.1:7001 127.0.0.1:7004
- >>> Adding node 127.0.0.1:7001 to cluster 127.0.0.1:7004
- 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:7004)
- M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004
- slots:5461-10922 (5462 slots) master
- 0 additional replica(s)
- M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000
- slots:0-5460 (5461 slots) master
- 1 additional replica(s)
- M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 127.0.0.1:7002
- slots:10923-16383 (5461 slots) master
- 1 additional replica(s)
- S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005
- slots: (0 slots) slave
- replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62
- S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003
- slots: (0 slots) slave
- replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7
- [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:7001: OK
- >>> Send CLUSTER MEET to node 127.0.0.1:7001 to make it join the cluster.
- [OK] New node added correctly.
默认add-node是添加主master节点,确认一下新添加的节点为master角色了。哈可以通过使用redis-trib.rb add-node –slave –master-id master-id 给指定的redis master节点添加从节点。
- [root@redis-cluster-yang 7001]# redis-trib check 127.0.0.1:7000
- Connecting to node 127.0.0.1:7000: 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:7004: 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)
- M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000
- slots:0-5460 (5461 slots) master
- 1 additional replica(s)
- S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005
- slots: (0 slots) slave
- replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62
- S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003
- slots: (0 slots) slave
- replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7
- M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004
- slots:5461-10922 (5462 slots) master
- 0 additional replica(s)
- M: 96f7aeaa57bf974be8eac4df54deeb96b66ff689 127.0.0.1:7001
- slots: (0 slots) master
- 0 additional replica(s)
- M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 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.
对集群进行重新分片reshard
- redis-trib reshard 127.0.0.1:7000
你只需要指定集群中其中一个节点的地址,
redis-trib
就会自动找到集群中的其他节点。
- How many slots do you want to move (from 1 to 16384)? 4000
除了移动的哈希槽数量之外,redis-trib
还需要知道重新分片的目标(target node),也即是,负责接收这些
哈希槽的节点。指定目标需要使用节点的 ID ,而不是 IP 地址和端口
- 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:all
输入 all
并按下回车之后,redis-trib
将打印出哈希槽的移动计划,如果你觉得没问题的话,就可以输入yes
并再次按下回车:
- $ ./redis-trib.rb reshard 127.0.0.1:7000
- ...
- Moving slot 11421 from 393c6df5eb4b4cec323f0e4ca961c8b256e3460a
- Moving slot 11422 from 393c6df5eb4b4cec323f0e4ca961c8b256e3460a
- Moving slot 5461 from e68e52cee0550f558b03b342f2f0354d2b8a083b
- Moving slot 5469 from e68e52cee0550f558b03b342f2f0354d2b8a083b
- ...
- Moving slot 5959 from e68e52cee0550f558b03b342f2f0354d2b8a083b
- Do you want to proceed with the proposed reshard plan (yes/no)? yes
确认分片后集群是否正常
- [root@redis-cluster-yang 7001]# redis-trib check 127.0.0.1:7000
- Connecting to node 127.0.0.1:7000: 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:7004: 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)
- M: 9c12c07dfbf10e56fea928ff7125f095b28a99d7 127.0.0.1:7000
- slots:1333-5460 (4128 slots) master
- 1 additional replica(s)
- S: 85dde9c952d3a6ffa7fbfe733734bc3a9113091c 127.0.0.1:7005
- slots: (0 slots) slave
- replicates d666a74d5bfce0d0cdeaab26fec4a1bed8beae62
- S: cda1b9a0e4242188f3296ed8d3ff0dbe5388dcb7 127.0.0.1:7003
- slots: (0 slots) slave
- replicates 9c12c07dfbf10e56fea928ff7125f095b28a99d7
- M: b59cfdc50d347695d5fa22ac0a2f10a4c1b398a7 127.0.0.1:7004
- slots:6795-10922 (4128 slots) master
- 0 additional replica(s)
- M: 96f7aeaa57bf974be8eac4df54deeb96b66ff689 127.0.0.1:7001
- slots:0-1332,5461-6794,10923-12255 (4000 slots) master
- 0 additional replica(s)
- M: d666a74d5bfce0d0cdeaab26fec4a1bed8beae62 127.0.0.1:7002
- slots:12256-16383 (4128 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.
故障转移测试
- 127.0.0.1:7001> KEYS *
- 1) "name"
- 127.0.0.1:7001> get name
- "yayun"
- 127.0.0.1:7001>
可以看见7001是正常的,并且获取到了key,value,现在kill掉7000实例,再进行查询。
- [root@redis-server ~]# ps -ef | grep 7000
- root 4168 1 0 11:49 ? 00:00:03 redis-server *:7000 [cluster]
- root 4385 4361 0 12:39 pts/3 00:00:00 grep 7000
- [root@redis-server ~]# kill 4168
- [root@redis-server ~]# ps -ef | grep 7000
- root 4387 4361 0 12:39 pts/3 00:00:00 grep 7000
- [root@redis-server ~]# redis-cli -c -p 7001
- 127.0.0.1:7001> get name
- "yayun"
- 127.0.0.1:7001>
可以正常获取到value,现在看看状态。
- [root@redis-server ~]# redis-cli -c -p 7001 cluster nodes
- 2d03b862083ee1b1785dba5db2987739cf3a80eb 127.0.0.1:7001 myself,master - 0 0 2 connected 5461-10922
- 0456869a2c2359c3e06e065a09de86df2e3135ac 127.0.0.1:7002 master - 0 1428295271619 3 connected 10923-16383
- 37b251500385929d5c54a005809377681b95ca90 127.0.0.1:7003 master - 0 1428295270603 7 connected 0-5460
- e2e2e692c40fc34f700762d1fe3a8df94816a062 127.0.0.1:7004 slave 2d03b862083ee1b1785dba5db2987739cf3a80eb 0 1428295272642 5 connected
- 2774f156af482b4f76a5c0bda8ec561a8a1719c2 127.0.0.1:7000 master,fail - 1428295159553 1428295157205 1 disconnected
- 9923235f8f2b2587407350b1d8b887a7a59de8db 127.0.0.1:7005 slave 0456869a2c2359c3e06e065a09de86df2e3135ac 0 1428295269587 6 connected
- [root@redis-server ~]#
原来的7000端口实例已经显示fail,原来的7003是slave,现在自动提升为master。
关于更多的在线添加节点,删除节点,以及对集群进行重新分片请参考官方文档。
总结
redis-cluster是个好东西,只是stable才出来不久,肯定坑略多,而且现在使用的人比较少,前期了解学习一下是可以的,生产环境肯定要慎重考虑。且需要进行严格的测试。生产环境中redis的集群可以考虑使用Twitter开源的twemproxy,以及豌豆荚开源的codis,这两个项目都比较成熟,现在使用的公司很多。已经向业界朋友得到证实。后面也会写博客介绍twemproxy和codis。
参考资料:
http://redis.readthedocs.org/en/latest/topic/cluster-tutorial.html
http://hot66hot.iteye.com/blog/2050676
http://redisdoc.com/topic/cluster-tutorial.html
http://xiaorui.cc/2015/05/16/%E9%80%9A%E8%BF%87redis-trib-rb%E8%84%9A%E6%9C%AC%E6%9E%84%E5%BB%BA%E5%B9%B6%E5%A2%9E%E5%88%A0%E6%94%B9%E6%9F%A5redis-cluster%E9%9B%86%E7%BE%A4/