:::info
注:本文基于Redis-6.2.4版本
因为redis5.0开始使用 redis-cli 作为创建集群的命令,使用c语言实现,不再使用ruby语言(所以Linux环境中也不用再安装Ruby)
:::
Redis Cluster
在前面的文章中介绍过了redis的主从和哨兵两种集群方案,redis从3.0版本开始引入了redis-cluster(集群)。从主从-哨兵-集群可以看到redis的不断完善;主从复制是最简单的节点同步方案无法主从自动故障转移。哨兵可以同时管理多个主从同步方案同时也可以处理主从自动故障转移,通过配置多个哨兵节点可以解决单点网络故障问题,但是单个节点的性能压力问题无法解决。集群解决了前面两个方案的所有问题。
- Redis-Cluster采用无中心结构,每个节点都和其它节点通过互ping保持连接,每个节点保存整个集群的状态信息,可以通过连接任意节点读取或者写入数据(甚至是没有数据的空节点)。
- 只有当集群中的大多数节点同时fail整个集群才fail。
- 整个集群有16384个slot,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个桶中。读取一个key时也是相同的算法。
- 当主节点fail时从节点会升级为主节点,fail的主节点online之后自动变成了从节点。
架构图
Redis为什么哈希槽的数量固定为16384?
总结一下:
- redis的一个节点的心跳信息中需要携带该节点的所有配置信息,而16K大小的槽数量所需要耗费的内存为2K,但如果使用65K个槽,这部分空间将达到8K,心跳信息就会很庞大。
- Redis集群中主节点的数量基本不可能超过1000个。
- Redis主节点的配置信息中,它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中,会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话,bitmap的压缩率就很低,所以N表示节点数,如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。而16K个槽当主节点为1000的时候,是刚好比较合理的,既保证了每个节点有足够的哈希槽,又可以很好的利用bitmap。
- 选取了16384是因为crc16会输出16bit的结果,可以看作是一个分布在0-2^16-1之间的数,redis的作者测试发现这个数对2^14求模的会将key在0-2^14-1之间分布得很均匀,因此选了这个值。
环境搭建
下载
还是和搭建单机版一样先下载安装包:Redis安装单机版复制配置文件
[root@redis-master redis-6.2.4]# mkdir cluster-conf
[root@redis-master redis-6.2.4]# cp redis.conf cluster-conf/redis-cluster-1.conf
[root@redis-master redis-6.2.4]# cp redis.conf cluster-conf/redis-cluster-2.conf
[root@redis-master redis-6.2.4]# cp redis.conf cluster-conf/redis-cluster-3.conf
[root@redis-master redis-6.2.4]# cp redis.conf cluster-conf/redis-cluster-4.conf
[root@redis-master redis-6.2.4]# cp redis.conf cluster-conf/redis-cluster-5.conf
[root@redis-master redis-6.2.4]# cp redis.conf cluster-conf/redis-cluster-6.conf
修改配置文件
依次将6个文件都修改一下,实际上可以先修改一个再复制哈哈 ```shell后台启动
daemonize yes修改端口号,16379 16380 16381 16382 16383 16384
port 16379
开启cluster,去掉注释
cluster-enabled yes
因为我是同一台机器上跑的,为了区分进程 16379 16380 16381 16382 16383 16384
pidfile “/var/run/redis_16379.pid”
存储redis集群配置信息,是系统自动生成 nodes-16379.conf nodes-16380.conf nodes-16381.conf nodes-16382.conf nodes-16383.conf nodes-16384.conf
cluster-config-file “/usr/local/redis-6.2.4/cluster-nodes/nodes-16379.conf”
节点通信时间
cluster-node-timeout 15000
持久化方式
appendonly yes
绑定ip
bind 0.0.0.0
认证密码
requirepass anin
<a name="CrRQC"></a>
### 启动redis
这里写了一个启动脚本方便一点
```shell
[root@redis-master redis-6.2.4]# vim start-cluster-all.sh
cd src
redis-server ../cluster-conf/redis-cluster-1.conf
redis-server ../cluster-conf/redis-cluster-2.conf
redis-server ../cluster-conf/redis-cluster-3.conf
redis-server ../cluster-conf/redis-cluster-4.conf
redis-server ../cluster-conf/redis-cluster-5.conf
redis-server ../cluster-conf/redis-cluster-6.conf
echo "OK"
ps -ef|grep redis
[root@redis-master redis-6.2.4]# chmod 777 start-cluster-all.sh
[root@redis-master redis-6.2.4]# ./start-cluster-all.sh
OK
root 1484 1 0 17:14 ? 00:00:00 redis-server 0.0.0.0:16379 [cluster]
root 1490 1 0 17:14 ? 00:00:00 redis-server 0.0.0.0:16380 [cluster]
root 1492 1 0 17:14 ? 00:00:00 redis-server 0.0.0.0:16381 [cluster]
root 1502 1 0 17:14 ? 00:00:00 redis-server 0.0.0.0:16382 [cluster]
root 1504 1 0 17:14 ? 00:00:00 redis-server 0.0.0.0:16383 [cluster]
root 1514 1 0 17:14 ? 00:00:00 redis-server 0.0.0.0:16384 [cluster]
root 1520 1394 0 17:14 pts/0 00:00:00 grep --color=auto redis
创建集群
[root@redis-master redis-6.2.4]# redis-cli --cluster create 127.0.0.1:16379 127.0.0.1:16380 127.0.0.1:16381 127.0.0.1:16382 127.0.0.1:16383 127.0.0.1:16384 -a anin --cluster-replicas 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 127.0.0.1:16383 to 127.0.0.1:16379
Adding replica 127.0.0.1:16384 to 127.0.0.1:16380
Adding replica 127.0.0.1:16382 to 127.0.0.1:16381
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: d3918d2cf9ce360132ce0403991a6486488cb90c 127.0.0.1:16379
slots:[0-5460] (5461 slots) master
M: a86d513d5a7d2e59d8ec4af3866438b3872c6f29 127.0.0.1:16380
slots:[5461-10922] (5462 slots) master
M: d75da7b006ae8f832529c04364af8bf20809d030 127.0.0.1:16381
slots:[10923-16383] (5461 slots) master
S: f55cff3cb03ebc3cdb0995d3f52f828da60a1d14 127.0.0.1:16382
replicates d3918d2cf9ce360132ce0403991a6486488cb90c
S: d45254a357654dbe8335696649061db0eb573a96 127.0.0.1:16383
replicates a86d513d5a7d2e59d8ec4af3866438b3872c6f29
S: b60cea5ec2997ce5a7b6af105bcba5620b321120 127.0.0.1:16384
replicates d75da7b006ae8f832529c04364af8bf20809d030
Can I set the above configuration? (type 'yes' to accept):
打印出一份预想中的配置给你看, 如果觉得没问题的话, 就可以输入 yes ,就会将这份配置应用到集群当中,让各个节点开始互相通讯,最后可以得到如下信息:
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:16379)
M: d3918d2cf9ce360132ce0403991a6486488cb90c 127.0.0.1:16379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: a86d513d5a7d2e59d8ec4af3866438b3872c6f29 127.0.0.1:16380
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: f55cff3cb03ebc3cdb0995d3f52f828da60a1d14 127.0.0.1:16382
slots: (0 slots) slave
replicates d3918d2cf9ce360132ce0403991a6486488cb90c
S: d45254a357654dbe8335696649061db0eb573a96 127.0.0.1:16383
slots: (0 slots) slave
replicates a86d513d5a7d2e59d8ec4af3866438b3872c6f29
S: b60cea5ec2997ce5a7b6af105bcba5620b321120 127.0.0.1:16384
slots: (0 slots) slave
replicates d75da7b006ae8f832529c04364af8bf20809d030
M: d75da7b006ae8f832529c04364af8bf20809d030 127.0.0.1:16381
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.
查看集群状态
[root@redis-master redis-6.2.4]# src/redis-cli -h 127.0.0.1 -p 16379 -a anin cluster info
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
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_ping_sent:134
cluster_stats_messages_pong_sent:146
cluster_stats_messages_sent:280
cluster_stats_messages_ping_received:141
cluster_stats_messages_pong_received:134
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:280
查看节点信息
[root@redis-master redis-6.2.4]# src/redis-cli -h 127.0.0.1 -p 16379 -a anin cluster nodes
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
a86d513d5a7d2e59d8ec4af3866438b3872c6f29 127.0.0.1:16380@26380 master - 0 1626679011049 2 connected 5461-10922
f55cff3cb03ebc3cdb0995d3f52f828da60a1d14 127.0.0.1:16382@26382 slave d3918d2cf9ce360132ce0403991a6486488cb90c 0 1626679012052 1 connected
d3918d2cf9ce360132ce0403991a6486488cb90c 127.0.0.1:16379@26379 myself,master - 0 1626679009000 1 connected 0-5460
d45254a357654dbe8335696649061db0eb573a96 127.0.0.1:16383@26383 slave a86d513d5a7d2e59d8ec4af3866438b3872c6f29 0 1626679010047 2 connected
b60cea5ec2997ce5a7b6af105bcba5620b321120 127.0.0.1:16384@26384 slave d75da7b006ae8f832529c04364af8bf20809d030 0 1626679011000 3 connected
d75da7b006ae8f832529c04364af8bf20809d030 127.0.0.1:16381@26381 master - 0 1626679009045 3 connected 10923-16383
集群关闭
集群关闭只需要关闭所以redis节点就可以了
[root@redis-master redis-6.2.4]# cat stop-cluster-all-sh
cd src
redis-cli -p 16379 -a anin shutdown
redis-cli -p 16380 -a anin shutdown
redis-cli -p 16381 -a anin shutdown
redis-cli -p 16382 -a anin shutdown
redis-cli -p 16383 -a anin shutdown
redis-cli -p 16384 -a anin shutdown
echo 'OK'
ps -ef|grep redis
集群重启
和上面的集群关闭一样,只需要全部再启动就可以了
[root@redis-master redis-6.2.4]# cat start-cluster-all.sh
cd src
redis-server ../cluster-conf/redis-cluster-1.conf
redis-server ../cluster-conf/redis-cluster-2.conf
redis-server ../cluster-conf/redis-cluster-3.conf
redis-server ../cluster-conf/redis-cluster-4.conf
redis-server ../cluster-conf/redis-cluster-5.conf
redis-server ../cluster-conf/redis-cluster-6.conf
echo "OK"
ps -ef|grep redis
删除集群
关闭所有redis节点,然后删除redis集群配置,看情况需不需要删除redis数据。
redis集群的配置就在我们刚才上面配置的地址。
[root@redis-master redis-6.2.4]# ll cluster-nodes/
总用量 24
-rw-r--r--. 1 root root 787 7月 19 15:35 nodes-16379.conf
-rw-r--r--. 1 root root 787 7月 19 15:35 nodes-16380.conf
-rw-r--r--. 1 root root 787 7月 19 15:35 nodes-16381.conf
-rw-r--r--. 1 root root 787 7月 19 15:35 nodes-16382.conf
-rw-r--r--. 1 root root 787 7月 19 15:34 nodes-16383.conf
-rw-r--r--. 1 root root 787 7月 19 15:35 nodes-16384.conf
遇到的问题
数据节点不为空
[ERR] Node 127.0.0.1:16379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.
解决办法:
把每个库都清掉
flushdb
提示我们不是所有的slot都被节点覆盖到
[ERR] Not all 16384 slots are covered by nodes.
解决办法:
官方的建议是使用fix修复
[root@redis-master src]# redis-cli --cluster fix