Redis5.0.10单机伪集群搭建
1、Redis集群概述
Redis cluster去除了中心化,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。
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 ,比如set k1 v1 ,按照Redis cluster的哈希槽算法:CRC16(‘k1’)%16384 = 2412。 那么就会把这个key 的存储分配到 A 上了。同样,当我连接(A,B,C)任何一个节点想获取k1这个key时,也会这样的算法,然后内部跳转到A节点上获取数据。这种哈希槽的分配方式有好也有坏,好处就是很清晰,比如我想新增一个节点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 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。举个例子,集群有A、B、C三个主节点,各自从节点为A1、B1、C1,那么如果C主节点挂掉了,C1结点就会自动代替上,变成主节点。所以我们在集群建立的时候,一定要为每个主节点都添加了从节点,从而达到高可用性。如果C节点和C1节点同时挂掉了,那么这个集群也会挂掉。
2、搭建集群
1、安装Redis
这里我就不多说什么了,参考:Redis学习(一)----简介与安装
2、修改配置,创建节点
我们进入Redis的安装目录,先创建redis_cluster目录,然后再分别在redis_cluster下创建7001、7002、7003、7004、7005、7006这6个目录。
然后将redis解压目录下的redis.conf配置文件复制过来。
将六个节点的 redis.conf 配置文件进行修改 ,修改以下几个:
- port 7001:六个节点配置文件分别是7001-7006
- daemonize yes:redis后台运行
- pidfile /var/run/redis_7001.pid:pidfile文件对应7001-7006
- logfile "7001.log":日志文件
- cluster-enabled yes:开启集群
- cluster-config-file nodes_7001.conf:保存节点配置,自动创建,更新对应7001-7006
- cluster-node-timeout 5000:集群超时时间,节点超过这个时间没反应就断定是宕机
①、修改端口
②、让redis以守护进程的方式运行,将 daemonize 改成yes
③、修改pidfile文件
④、修改日志文件
⑤、 开启集群,打开注释cluster-enabled yes,这里必须打开,很重要。
⑥、 保存节点配置
⑦、设置集群超时时间
分别将7001-7006配置一遍。
3、编写Redis集群启动脚本
编写集群的启动和停止shell脚本,这样方便:
vi start.sh 加入下面内容:
/usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/7001/redis.conf /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/7002/redis.conf /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/7003/redis.conf /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/7004/redis.conf /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/7005/redis.conf /usr/local/redis/bin/redis-server /usr/local/redis/redis_cluster/7006/redis.conf
vi stop.sh 加入下面内容:
/usr/local/redis/bin/redis-cli -p 7001 shutdown /usr/local/redis/bin/redis-cli -p 7002 shutdown /usr/local/redis/bin/redis-cli -p 7003 shutdown /usr/local/redis/bin/redis-cli -p 7004 shutdown /usr/local/redis/bin/redis-cli -p 7005 shutdown /usr/local/redis/bin/redis-cli -p 7006 shutdown
修改权限:
chmod 755 start.sh stop.sh
然后启动所有节点
4、启动集群
注意:在启动集群的时候redis数据库必须是空的,否则会报错提示:[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。
解决方法:删除生成的配置文件nodes.conf,如果不行则说明现在创建的结点包括了旧集群的结点信息,需要删除redis的持久化文件后再重启redis,比如:appendonly.aof、dump.rdb。
在Redis3.0的版本启动集群使用的命令是:redis-trib.rb create --replicas 1 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 127.0.0.1:7006 ,Redis官方提供了redis-trib.rb工具,但是在使用之前需要安装ruby,以及redis和ruby连接工具。
但是Redis5.0集群管理工具redis-trib.rb已经被废弃,所以不用安装ruby啥的了,现在已经集成到了redis-cli中,并且可以在有认证的情况执行了,可以通过redis-cli --cluster help查看使用方式。
[root@localhost redis_cluster]# cd /usr/local/redis/bin/ [root@localhost bin]# ./redis-cli --cluster help Cluster Manager Commands: create host1:port1 ... hostN:portN --cluster-replicas <arg> check host:port --cluster-search-multiple-owners info host:port fix host:port --cluster-search-multiple-owners reshard host:port --cluster-from <arg> --cluster-to <arg> --cluster-slots <arg> --cluster-yes --cluster-timeout <arg> --cluster-pipeline <arg> --cluster-replace rebalance host:port --cluster-weight <node1=w1...nodeN=wN> --cluster-use-empty-masters --cluster-timeout <arg> --cluster-simulate --cluster-pipeline <arg> --cluster-threshold <arg> --cluster-replace add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id <arg> del-node host:port node_id call host:port command arg arg .. arg set-timeout host:port milliseconds import host:port --cluster-from <arg> --cluster-copy --cluster-replace help For check, fix, reshard, del-node, set-timeout you can specify the host and port of any working node in the cluster. [root@localhost bin]#
启动集群,直接一个命令就OK:
./redis-cli --cluster create 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 127.0.0.1:7006 --cluster-replicas 1
从上面的运行结果看,默认给的 主节点就是7001 7002 7003 ,从节点分别是7004 7005 7006 (三主三从)
- 7001分配到的哈希槽是 0-5460
- 7002分配到的哈希槽是 5461-10922
- 7003分配到的哈希槽是 10923-16383
这样16384个卡槽全部分配完毕,集群创建成功,可以使用了。
5、添加主从节点到集群中
我们新建两个目录7007、7008用于给集群添加一个主从节点:
同样的方法修改7007、7008的 redis.conf 配置文件。然后启动它们:
启动成功。
①、添加Master主节点
注意:在启动集群的时候redis数据库必须是空的,否则会报错提示:[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。
解决方法:删除生成的配置文件nodes.conf,如果不行则说明现在创建的结点包括了旧集群的结点信息,需要删除redis的持久化文件后再重启redis,比如:appendonly.aof、dump.rdb。
./redis-cli --cluster add-node 127.0.0.1:7007 127.0.0.1:7001
然后查看redis集群信息:
./redis-cli --cluster check 127.0.0.1:7001
可以看到 7007端口作为master 主节点加入到redis集群中 ,但 7007 没有slots卡槽
使用下面命令为7007端口增加卡槽:
./redis-cli --cluster reshard 127.0.0.1:7007
然后查看分配卡槽的信息:
分配成功!
②、添加Slave节点
我们给Master主节点7007添加一个从节点7008:
# 127.0.0.1:7008 节点的ip和端口 # 127.0.0.1:7001 已存在集群中的一个节点ip和端口 # add-node 添加一个节点 # --cluster-slave 从节点 # --cluster-master-id 该从节点的master节点id ./redis-cli --cluster add-node 127.0.0.1:7008 127.0.0.1:7001 --cluster-slave --cluster-master-id e3ed175cd38c9ea5b7a0827f2be7b8bfa9385ba2
然后查看集群的信息:
./redis-cli --cluster check 127.0.0.1:7001
可以发现7008端口已经成为了7007端口的从节点。
③、删除 slave从节点
./redis-cli --cluster del-node 127.0.0.1:7008 609e99ae01ce067323f8c44207f512b5cd3546e2
成功删除7008从节点。
④、删除Master主节点
要删除master节点,首先要将它的 slot卡槽全部提取到别的master节点上:
./redis-cli --cluster reshard 127.0.0.1:7001
查看一下集群信息:
此时7007节点上的slot卡槽已经是0个了:
如果想卡槽分配均匀,可以使用如下命令:
./redis-cli --cluster rebalance --cluster-threshold 1 127.0.0.1:7001
删除 7007 master节点
./redis-cli --cluster del-node 127.0.0.1:7007 73f19b384906113507b25f256a781ce184777162 ./redis-cli --cluster check 127.0.0.1:7001
删除成功。
6、集群数据测试
我们先连接Redis任意一个节点端口:
./redis-cli -c -p 7001 # -c 表示集群 -p是端口
这就是Redis Cluster值分配规则,所以分配key的时候,它会使用CRC16(‘k1’)%16384算法,来计算,将这个key 放到哪个节点,这里分配到了12706 slot 就分配到了7003这个节点上。
我们在其他的节点上也能获取到这个值。
7、集群宕机测试
我们来挂掉一个节点测试一下,如果将7001节点kill掉:
我们再来查看一下集群的信息(./redis-cli --cluster check 127.0.0.1:7002):
可以发现集群并没有挂掉,这是因为7006本来是7001的从节点,结果发现7001节点挂了,然后7006节点顶上去,变成了Master主节点。
那么我们把7006也给它干死,会怎么样呢?
再次查看集群节点信息;
这里发现出现了错误,说有一些 哈希槽没得分配,也说明了Redis集群必须要三个结点才能创建成功!
[ERR] Not all 16384 slots are covered by nodes. 没有安全覆盖;所以不能正常使用集群了;