系统环境
CentOS 7
集群规划
在一台物理机(实际部署应当分散到多个物理机上),创建6个Redis节点,其中3个主节点、3个从节点。
节点表:
IP 端口 主从 路径
192.168.1.21 7001 主 ~/redis-cluster/7001/
192.168.1.21 7002 主 ~/redis-cluster/7002/
192.168.1.21 7003 主 ~/redis-cluster/7003/
192.168.1.21 7011 从 ~/redis-cluster/7011/
192.168.1.21 7012 从 ~/redis-cluster/7012/
192.168.1.21 7013 从 ~/redis-cluster/7013/
创建步骤
01. 准备环境
# yum install gcc
# yum install ruby
# yum install ruby-devel.x86_64
# yum install rubygems
# gem sources -r https://rubygems.org
# gem sources -a http://rubygems.org
# gem install redis
02. 下载安装 redis
# cd~
# wget http://download.redis.io/releases/redis-3.0.7.tar.gz
# tar zxfv redis-3.0.7.tar.gz
# cd redis-3.0.7
# make MALLOC=libc
# cp src/redis-server /usr/local/bin
# cp src/redis-cli /usr/local/bin
# cp src/redis-trib.rb /usr/local/bin
03. 独立启动/停止 redis
# redis-server &
# redis-cli shutdown
04. 测试独立 redis
# redis-cli -p 7001
127.0.0.1:7001> set mykey myval01
127.0.0.1:7001> get mykey
"myval01"
05. 建立集群环境
# cd~
# mkdir redis-cluster
# cd redis-cluster
# mkdir 7001 7002 7003 7011 7012 7013
创建配置文件 ~/redis-cluster/redis.conf,内容如下:
port 7001
daemonize yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
文件中的 cluster-enabled 选项用于开实例的集群模式, 而 cluster-conf-file 选项则设定了保存节点配置文件的路径, 默认值为 nodes.conf。该节点配置文件无须人为修改,它由Redis集群在启动时自动创建, 并在有需要时自动进行更新。
若要让集群正常运作至少需要三个主节点,我们的环境中,每个主节点附带一个从节点,所以一共六个节点。
为每个节点创建配置文件
# cd ~/redis-cluster
# cp redis.conf ./7001/
# …
# cp redis.conf ./7013/
修改各个目录下的 redis.conf 文件中的 port 为各自对应的端口
06. 启动各个节点
# cd ~/redis-cluster
# cd 7001
# redis-server redis.conf
# cd ../7002
# redis-server redis.conf
# …
# cd ../7013
# redis-server redis.conf
查看redis的启动情况
# ps -ef | grep redis
07. 创建集群
现在我们已经有了六个正在运行中的 Redis 实例, 接下来我们需要使用这些实例来创建集群。
通过使用 Redis 集群命令行工具 redis-trib , 编写节点配置文件的工作可以非常容易地完成: redis-trib 位于 Redis 源码的 src 文件夹中, 它是一个 Ruby 程序, 这个程序通过向实例发送特殊命令来完成创建新集群, 检查集群, 或者对集群进行重新分片(reshared)等工作。这里通过create命令来创建集群。
# cd ~/redis-3.0.0/src
# ./redis-trib.rb create --replicas 1 192.168.1.21:7001 192.168.1.21:7002 192.168.1.21:7003 192.168.1.21:7011 192.168.1.21:7012 192.168.1.21:7013
说明:
这里的IP地址必须是真实的IP,不能使用回环 127.0.0.1 地址。
–replicas 1 即每一个master有1个slave;顺序为 m m m s s s
redis-trib 会打印出一份预想中的配置给你看, 如果你觉得没问题的话, 就可以输入 yes , redis-trib 就会将这份配置应用到集群当中,让各个节点开始互相通讯。
输入yes,然后配置完成。
以上信息的其中一部分可以通过向集群中的任意节点(主节点或者从节点都可以)发送 CLUSTER NODES 命令来获得。该命令还可以获得节点 ID , IP 地址和端口号, 标志(flag), 最后发送 PING 的时间, 最后接收 PONG 的时间, 连接状态, 节点负责处理的槽。
# redis-cli -p 7001 cluster nodes
08. 集群检查
./redis-trib.rb check 127.0.0.1:7001
09. 连接Redis集群
通过上面的输出,我们可以看出Redis三个主节点的slot范围。一个 Redis 客户端可以向集群中的任意节点(包括从节点)发送命令请求。我们首先连接第一个节点:
# redis-cli -p 7001
127.0.0.1:7001> set a 1
(error) MOVED 15495 127.0.0.1:7003
127.0.0.1:7001> get a
(error) MOVED 15495 127.0.0.1:7003
127.0.0.1:7001> set b 1
OK
虽然我们用Node ID来标识集群中的节点, 但是为了让客户端的转向操作尽可能地简单, 节点在 MOVED 错误中直接返回目标节点的 IP 和端口号, 而不是目标节点的 ID 。客户端应该记录槽15495由节点127.0.0.1:7003负责处理“这一信息, 这样当再次有命令需要对槽15495执行时, 客户端就可以加快寻找正确节点的速度。这样,当集群处于稳定状态时,所有客户端最终都会保存有一个哈希槽至节点的映射记录,使得集群非常高效: 客户端可以直接向正确的节点发送命令请求, 无须转向、代理或者其他任何可能发生单点故障(single point failure)的实体(entiy)。
10. 添加新master节点
a. 启动节点
# cd ~/redis-cluster
# mkdir 8001
# cp ./redis.conf ./8001
# cd 8001
# redis-server redis.conf
b. 将节点加入到集群
# redis-trib.rb add-node 127.0.0.1:8001 127.0.0.1:7001
说明:
第一个 ip:port 为新节点
第二个 ip:port 是任意一个已经存在的节点
新节点没有包含任何数据,也没有包含任何slot。
当集群需要将某个从节点升级为新的主节点时, 这个新节点不会被选中,同时新的主节点因为没有包含任何slot,不参加选举和failover。
c. 为新节点分配 slot
# redis-trib.rb reshard 127.0.0.1:8001
#根据提示选择要迁移的slot数量(ps:这里选择500)
How many slots do you want to move (from 1 to 16384)? 500
#选择要接受这些slot的node-id
What is the receiving node ID? f51e26b5d5ff74f85341f06f28f125b7254e61bf
#选择slot来源:
#all表示从所有的master重新分配,
#或者数据要提取slot的master节点id,最后用done结束
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
#打印被移动的slot后,输入yes开始移动slot以及对应的数据.
#Do you want to proceed with the proposed reshard plan (yes/no)? yes
#结束
11. 添加新的 Slave 节点
a. 启动节点
# cd ~/redis-cluster
# mkdir 8011
# cp ./redis.conf ./8011
# cd 8011
# redis-server redis.conf
b. 将节点加入到集群
方法一:
# redis-trib.rb add-node -slave 127.0.0.1:8011 127.0.0.1:7001
说明:
第一个 ip:port 为新节点
第二个 ip:port 是任意一个已经存在的节点
新的节点会作为集群中其中一个主节点的从节点,一般来说是从节点最少的主节点。
方法二:
# redis-trib.rb add-node -slave -master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e 127.0.0.1:8011 127.0.0.1:7001
说明:
-master-id xxxx 主节点的 ID
第一个 ip:port 为新节点
第二个 ip:port 是任意一个已经存在的节点
注意:在线添加slave 时,需要bgsave整个master数据,并传递到slave,再由 slave加载rdb文件到内存,rdb生成和传输的过程中消耗Master大量内存和网络IO,以此不建议单实例内存过大,线上小心操作。
12. 在线 reshard 数据
对于负载/数据不均匀的情况,可以在线reshard slot来解决,方法与添加新master的reshard一样,只是需要reshard的master节点是已存在的老节点。
# redis-trib.rb reshard 127.0.0.1:7003
13. 删除一个 slave 节点
# redis-trib.rb del-node ip:port '<node-id>'
# redis-trib.rb del-node 127.0.0.1:7001 'c7ee2fca17cb79fe3c9822ced1d4f6c5e169e378'
说明:
ip:port 集群中已有的任意一节点(不是被删除的节点)
被删除节点的 ID
14. 删除一个 master 节点(7003)
删除master节点之前首先要使用reshard移除master的全部slot,然后再删除当前节点。 (目前redis-trib.rb只能把被删除master的slot对应的数据迁移到一个节点上)。
a. 迁移 slot
#把127.0.0.1:7003当前master迁移到127.0.0.1:7002上
redis-trib.rb reshard 172.0.0.1:7002
#根据提示选择要迁移的slot数量(ps:这里选择500)
How many slots do you want to move (from 1 to 16384)? 500(被删除master的所有slot数量)
#选择要接受这些slot的node-id(172.0.0.1:7002)
What is the receiving node ID? c4a31c852f81686f6ed8bcd6d1b13accdc947fd2 (ps:172.0.0.1:7002的node-id)
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:f51e26b5d5ff74f85341f06f28f125b7254e61bf(被删除master的node-id)
Source node #2:done
#打印被移动的slot后,输入yes开始移动slot以及对应的数据.
#Do you want to proceed with the proposed reshard plan (yes/no)? yes
b. 删除空的 master 节点
# redis-trib.rb del-node 172.0.0.1:7001 'f51e26b5d5ff74f85341f06f28f125b7254e61bf'
说明:
ip:port 集群中已有的任意一节点(不是被删除的节点)
被删除节点的 ID
15. 改变从节点的隶属关系(从节点 7013)
# redis-cli -p 7013
127.0.0.1:7013> cluster replicate 2b9ebcbd627ff0fd7a7bbcc5332fb09e72788835
说明:
2b9ebcbd627ff0fd7a7bbcc5332fb09e72788835 为新的主节点的 ID
16. 集群的关闭和重启
redis cluster官方文档,没发现有关集群重启和关闭的方法。主要是因为在正式的环境中集群一般都由3台物理机构成,3台物理机同时挂掉的可能性极小。只要不同时挂掉,挂掉的机器修复后在加入集群,集群都能良好的运作,万一同时挂掉,数据又没有备份的话,就有大麻烦了。
redis cluster集群中的节点基本上都对等的,没有管理节点。如果要让所有节点都关闭,只能关闭所有 redis-server 进程。
# pkill -9 redis
然后重新启动,如果直接重启会报告错误。
# redis-trib.rb create --replicas 1 xxx xxx xxx xxx
会报以下错误,
[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.
第一次启动集群时,~/redis-cluster/7001/ 下只有 redis.conf,而现在重启时,此目录下有了别的文件,所有报错。简单的方法是将除了 redis.conf 外的其他文件全部删除,在启动肯定是可以的,但是集群是有数据的,所以需要保留了配置文件 redis.conf 和数据文件 *.rdb。
这样是可以启动的,但是原来的数据还是丢失了,不知道是自己的想法不对。
需要注意的问题
-
执行06步骤时,节点目录下(7001/7002/…/7013/ 应当只有 redis.conf 文件)
-
一定要严格执行 01 步骤准备好环境。
此步骤中 gem sources 默认地址好像无法访问,建议用下面方法替换
# gem sources -r https://rubygems.org
# gem sources -a http://rubygems.org