Redis Cluster 集群使用(3)

简介

Redis3.0版本之前,可以通过Redis Sentinel(哨兵)来实现高可用(HA),从3.0版本之后,官方推出了Redis Cluster,它的主要用途是实现数据分片(Data Sharding),不过同样可以实现HA,是官方当前推荐的方案。
在Redis Sentinel模式中,每个节点需要保存全量数据,冗余比较多,而在Redis Cluster模式中,每个分片只需要保存一部分的数据,对于内存数据库来说,还是要尽量的减少冗余。在数据量太大的情况下,故障恢复需要较长时间。

Redis Cluster本身提供了自动将数据分散到Redis Cluster不同节点的能力,分区实现的关键点问题包括:

  1. 如何将数据自动的打散到不同的节点,使得不同节点的存储数据相对均匀;
  2. 如何保证客户端能够访问到正确的节点和数据;
  3. 如何保证重新分片的过程中不影响正常服务。

数据分区

(这部分的资料来自于:https://blog.csdn.net/qq2430/article/details/80716313 感谢作者的分享)

在介绍Redis Cluster之前,先简单介绍下分布式数据库的数据分区。所谓的数据分区就是将一个较大的数据集分布在不同的节点上进行储存。

常见的数据分区方式:

  1. 节点取余;
  2. 一致性哈希;
  3. 虚拟槽

【节点取余】

根据key的hash值和节点数取模的方式计算出节点ID,然后向对应的节点提交数据,如下:

对于这种分区方式,新增或者删除节点会造成大量的数据迁移。假设数据集为:1 2 3... 10,那么数据分布应如下所示:

如果新增一个节点,那么数据分布会变成什么样子呢?

比较结果:只有 1、2、3还分布在原来的节点上,其余所有的数据都进行了迁移。在这种分区方式下,如果新增的节点时原来节点的倍数时,迁移的节点数量会少很多。

【一致性哈希】

对于任何的哈希函数,都有其取值范围。我们可以用环形结构来标识范围。通过哈希函数,每个节点都会被分配到环上的一个位置,每个键值也会被映射到环上的一个位置,然后顺时针找到相邻的节点。如下图所示,例如key分布在range1内,那么数据存储在node2上。

对于这种分区方式,新增或者删除节点会造成数据分布不均匀。假设数据集 1 2 3 ... 12,数据范围也是1-12,那么数据分布应如下所示:

如果我们在node1和node2之间新增一个节点,那么数据分布应该变成什么样子呢?

可以看到,我们只是将数据3进行了迁移。但是造成了每个节点负责的数据范围不等。会造成数据分布不均等的问题。

 

【虚拟槽】

在 redis cluster中使用槽来存储一定范围内的数据集。每个redis节点上有一定数量的槽。当客户端提交数据时,要先根据CRC16(key)&16383来计算出数据要落到哪个虚拟槽内。

假设我们有3个节点,那么可以按如下分配槽:

与节点取余和一致性哈希分区不同,虚拟槽分区是服务端分区。客户端可以将数据提交到任意一个redis cluster 节点上,如果存储该数据的槽不在这个节点上,则返回给客户端目标节点信息,告知客户端向目标节点提交数据。

Redis Cluster 原理介绍

RedisCluster是由多个同时服务于一个数据集合的Redis实例组成的整体,对于用户来说,用户只关注这个数据集合,而整个数据集合的某个数据子集存储在哪个节点对于用户来说是透明的。

redis cluster采用无中心结构,节点间使用gossip协议进行通信。每个节点保存数据和所有节点对应槽的映射关系。其架构图如下:

Redis Cluster 特点如下:

  1. 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
  2. 节点的fail是通过集群中超过半数的节点检测失效时才生效。
  3. 客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
  4. redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node -> slot -> value
  5. 集群消息通信通过集群总线通信,集群总线端口大小为客户端服务端口+10000,这个10000是固定值;
  6. 客户端和集群节点之间通信和通常一样,通过文本协议进行;
  7. 集群节点不会代理查询

Redis Cluster的具体实现细节是采用了Hash槽的概念,集群会预先分配16384个槽,并将这些槽分配给具体的服务节点,通过对Key进行CRC16(key)%16384运算得到对应的槽是哪一个,从而将读写操作转发到该槽所对应的服务节点。当有新的节点加入或者移除的时候,再来迁移这些槽以及其对应的数据。在这种设计之下,我们就可以很方便的进行动态扩容或缩容。

【Redis Cluster投票:容错】

  1. 投票过程是集群中所有master参与,如果半数以上master节点与master节点通信超时(cluster-node-timeout),认为当前master节点挂掉,对应master节点挂掉,slave会代替工作
  2. 如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态.

Redis Cluster集群搭建

(因为资源有限,本次在同一台主机上实现Redis Cluster)

1. 安装不同端口的 6 个 redis 节点

[root@192.168.118.15 /usr/local/src]#yum install gcc* -y
[root@192.168.118.15 /usr/local/src]#ls
redis-4.0.10.tar.gz
[root@192.168.118.15 /usr/local/src]#tar xf redis-4.0.10.tar.gz 
[root@192.168.118.15 /usr/local/src]#cd redis-4.0.10
[root@192.168.118.15 /usr/local/src/redis-4.0.10]#mkdir -pv /usr/local/redis/{conf,db,log}
mkdir: created directory ‘/usr/local/redis’
mkdir: created directory ‘/usr/local/redis/conf’
mkdir: created directory ‘/usr/local/redis/db’
mkdir: created directory ‘/usr/local/redis/log’
[root@192.168.118.15 /usr/local/src/redis-4.0.10]#make PREFIX=/usr/local/redis/ install 

编译完成后,修改配置文件

[root@192.168.118.15 /usr/local/src/redis-4.0.10]#mkdir -pv  /usr/local/redis/conf/63{79..84}
mkdir: created directory ‘/usr/local/redis/conf/6379mkdir: created directory ‘/usr/local/redis/conf/6380mkdir: created directory ‘/usr/local/redis/conf/6381mkdir: created directory ‘/usr/local/redis/conf/6382mkdir: created directory ‘/usr/local/redis/conf/6383mkdir: created directory ‘/usr/local/redis/conf/6384’
[root@192.168.118.15 /usr/local/src/redis-4.0.10]#for i in 6379 6380 6381 6382 6383 6384; do cp -a redis.conf /usr/local/redis/conf/$i/$i.conf ; done
[root@192.168.118.15 /usr/local/src/redis-4.0.10]#yum install tree -y
[root@192.168.118.15 /usr/local/src/redis-4.0.10]#cd /usr/local/redis/
[root@192.168.118.15 /usr/local/redis]#tree 
.
├── bin
│   ├── redis-benchmark
│   ├── redis-check-aof
│   ├── redis-check-rdb
│   ├── redis-cli
│   ├── redis-sentinel -> redis-server
│   └── redis-server
├── conf
│   ├── 6379
│   │   └── 6379.conf
│   ├── 6380
│   │   └── 6380.conf
│   ├── 6381
│   │   └── 6381.conf
│   ├── 6382
│   │   └── 6382.conf
│   ├── 6383
│   │   └── 6383.conf
│   └── 6384
│       └── 6384.conf
├── db
└── log

10 directories, 12 files

编写修改配置文件脚本

[root@192.168.118.15 /usr/local/redis/conf]#vim modify_conf.sh
#!/bin/bash
for i in 6379  6380  6381  6382  6383  6384; do
  sed -i "s/daemonize no/daemonize yes/g" $i/$i.conf
  sed -i "s/bind 127.0.0.1/bind 0.0.0.0/g" $i/$i.conf
  sed -i "s/port 6379/port $i/g" $i/$i.conf
  sed -i "s/dbfilename dump.rdb/dbfilename dump-$i.rdb/g" $i/$i.conf
  sed -i "s/redis_6379.pid/redis_$i.pid/g" $i/$i.conf
  sed -i "s/dir .//dir /usr/local/redis/db//g" $i/$i.conf
  sed -i "s/logfile ""/logfile "/usr/local/redis/log/redis-$i.log"/g" $i/$i.conf
  sed -i "s/# cluster-enabled yes/cluster-enabled yes/g" $i/$i.conf
  sed -i "s/# cluster-config-file nodes-6379.conf/cluster-config-file nodes-$i.conf/g" $i/$i.conf
  sed -i "s/# cluster-node-timeout 15000/cluster-node-timeout 15000/g" $i/$i.conf
done

[root@192.168.118.15 /usr/local/redis/conf]#sh modify_conf.sh
sed -i "s/daemonize no/daemonize yes/g" $i/$i.conf    # 修改为后台运行
sed -i "s/bind 127.0.0.1/bind 0.0.0.0/g" $i/$i.conf    # 修改监听ip
sed -i "s/port 6379/port $i/g" $i/$i.conf    # 修改监听端口
sed -i "s/dbfilename dump.rdb/dbfilename dump-$i.rdb/g" $i/$i.conf    # 修改RDB模式持久化文件名
sed -i "s/redis_6379.pid/redis_$i.pid/g" $i/$i.conf    # 修改pid文件名
sed -i "s/dir .//dir /usr/local/redis/db//g" $i/$i.conf    # 修改文件保存目录
sed -i "s/logfile ""/logfile "/usr/local/redis/log/redis-$i.log"/g" $i/$i.conf    # 修改日志文件目录及文件名
sed -i "s/# cluster-enabled yes/cluster-enabled yes/g" $i/$i.conf    # 开启集群模式
sed -i "s/# cluster-config-file nodes-6379.conf/cluster-config-file nodes-$i.conf/g" $i/$i.conf    # 定义集群配置文件(该文件无需手动创建,启动自动生成)
sed -i "s/# cluster-node-timeout 15000/cluster-node-timeout 15000/g" $i/$i.conf    # 开启集群节点无法连接超时时间
修改的配置各项注解

启动服务

[root@192.168.118.15 /usr/local/redis/conf]#echo "export PATH=$PATH:/usr/local/redis/bin" > /etc/profile.d/redis.sh
[root@192.168.118.15 /usr/local/redis/conf]#source /etc/profile.d/redis.sh
[root@192.168.118.15 /usr/local/redis/conf]#for i in 6379  6380  6381  6382  6383  6384; do redis-server $i/$i.conf ; done
[root@192.168.118.15 /usr/local/redis/conf]#netstat -ntplu | egrep redis
tcp        0      0 0.0.0.0:16379           0.0.0.0:*               LISTEN      5520/redis-server 0 
tcp        0      0 0.0.0.0:16380           0.0.0.0:*               LISTEN      5522/redis-server 0 
tcp        0      0 0.0.0.0:16381           0.0.0.0:*               LISTEN      5524/redis-server 0 
tcp        0      0 0.0.0.0:16382           0.0.0.0:*               LISTEN      5526/redis-server 0 
tcp        0      0 0.0.0.0:16383           0.0.0.0:*               LISTEN      5531/redis-server 0 
tcp        0      0 0.0.0.0:16384           0.0.0.0:*               LISTEN      5533/redis-server 0 
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN      5520/redis-server 0 
tcp        0      0 0.0.0.0:6380            0.0.0.0:*               LISTEN      5522/redis-server 0 
tcp        0      0 0.0.0.0:6381            0.0.0.0:*               LISTEN      5524/redis-server 0 
tcp        0      0 0.0.0.0:6382            0.0.0.0:*               LISTEN      5526/redis-server 0 
tcp        0      0 0.0.0.0:6383            0.0.0.0:*               LISTEN      5531/redis-server 0 
tcp        0      0 0.0.0.0:6384            0.0.0.0:*               LISTEN      5533/redis-server 0

redis端口 --> 集群总线端口

6379 --> 16379
6380 --> 16380
6381 --> 16381
6382 --> 16382
6383 --> 16383
6384 --> 16384

redis cluster 集群创建

由于创建集群需要用到redis-trib这个命令,它依赖Ruby和RubyGems,因此我们要先安装一下

[root@192.168.118.15 /usr/local/redis/conf]#yum install ruby rubygems -y

这里要注意下:查看ruby对应的版本下载支持的 redis.gem,具体对应关系及下载可以查看 https://rubygems.org/downloads/

[root@192.168.118.15 /usr/local/redis/conf]#ruby --version
ruby 2.0.0p353 (2013-11-22) [x86_64-linux]

下载redis-3.3.3.gem
[root@192.168.118.15 ~]#yum install wget -y
[root@192.168.118.15 ~]#wget https://rubygems.org/downloads/redis-3.3.3.gem --no-check-certificate
[root@192.168.118.15 ~]#gem install redis-3.3.3.gem     # 安装redis.gem
Successfully installed redis-3.3.3
Parsing documentation for redis-3.3.3
Installing ri documentation for redis-3.3.3
1 gem installed
[root@192.168.118.15 ~]#gem list

*** LOCAL GEMS ***

bigdecimal (1.2.0)
io-console (0.4.2)
json (1.7.7)
psych (2.0.0)
rdoc (4.0.0)
redis (3.3.3)    # 安装成功

创建集群
注意:redis-trib.rb 命令在 源码的 src里面

[root@192.168.118.15 ~]#cp -a /usr/local/src/redis-4.0.10/src/redis-trib.rb /usr/local/redis/bin/
[root@192.168.118.15 ~]#redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
127.0.0.1:6379
127.0.0.1:6380
127.0.0.1:6381
Adding replica 127.0.0.1:6383 to 127.0.0.1:6379
Adding replica 127.0.0.1:6384 to 127.0.0.1:6380
Adding replica 127.0.0.1:6382 to 127.0.0.1:6381
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 7bb6e7b6b77db35a306ff932a8a70277763e3504 127.0.0.1:6379
   slots:0-5460 (5461 slots) master
M: a798db2f4e6a756606677bf82b0488c517402412 127.0.0.1:6380
   slots:5461-10922 (5462 slots) master
M: 292362ebc26df9920de8e8c19fdad0d9a5e05fb7 127.0.0.1:6381
   slots:10923-16383 (5461 slots) master
S: fd583297b826fc92bc872d5a3a6e8bfda30a5eda 127.0.0.1:6382
   replicates 7bb6e7b6b77db35a306ff932a8a70277763e3504
S: a6d4cb574131b82d95f58c92c9fe5389dcb16f59 127.0.0.1:6383
   replicates a798db2f4e6a756606677bf82b0488c517402412
S: d984d502c61d2b3d64b0100a0179642d92c9f95d 127.0.0.1:6384
   replicates 292362ebc26df9920de8e8c19fdad0d9a5e05fb7
Can I set the above configuration? (type 'yes' to accept): yes    # 这里需要手动输入 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:6379)
M: 7bb6e7b6b77db35a306ff932a8a70277763e3504 127.0.0.1:6379
   slots:0-5460 (5461 slots) master
   1 additional replica(s)
S: fd583297b826fc92bc872d5a3a6e8bfda30a5eda 127.0.0.1:6382
   slots: (0 slots) slave
   replicates 7bb6e7b6b77db35a306ff932a8a70277763e3504
S: a6d4cb574131b82d95f58c92c9fe5389dcb16f59 127.0.0.1:6383
   slots: (0 slots) slave
   replicates a798db2f4e6a756606677bf82b0488c517402412
S: d984d502c61d2b3d64b0100a0179642d92c9f95d 127.0.0.1:6384
   slots: (0 slots) slave
   replicates 292362ebc26df9920de8e8c19fdad0d9a5e05fb7
M: a798db2f4e6a756606677bf82b0488c517402412 127.0.0.1:6380
   slots:5461-10922 (5462 slots) master
   1 additional replica(s)
M: 292362ebc26df9920de8e8c19fdad0d9a5e05fb7 127.0.0.1:6381
   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.

到此,Redis Cluster 已经搭建成功。

连接其中一个节点查看集群状态:

[root@192.168.118.15 ~]#redis-cli -h 127.0.0.1 -p 6379 
127.0.0.1:6379> 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_ping_sent:86
cluster_stats_messages_pong_sent:85
cluster_stats_messages_sent:171
cluster_stats_messages_ping_received:80
cluster_stats_messages_pong_received:86
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:171

# 查看集群节点状态
127.0.0.1:6379> cluster nodes 
fd583297b826fc92bc872d5a3a6e8bfda30a5eda 127.0.0.1:6382@16382 slave 7bb6e7b6b77db35a306ff932a8a70277763e3504 0 1544091668241 4 connected
a6d4cb574131b82d95f58c92c9fe5389dcb16f59 127.0.0.1:6383@16383 slave a798db2f4e6a756606677bf82b0488c517402412 0 1544091668000 5 connected
7bb6e7b6b77db35a306ff932a8a70277763e3504 127.0.0.1:6379@16379 myself,master - 0 1544091668000 1 connected 0-5460
d984d502c61d2b3d64b0100a0179642d92c9f95d 127.0.0.1:6384@16384 slave 292362ebc26df9920de8e8c19fdad0d9a5e05fb7 0 1544091669244 6 connected
a798db2f4e6a756606677bf82b0488c517402412 127.0.0.1:6380@16380 master - 0 1544091669000 2 connected 5461-10922
292362ebc26df9920de8e8c19fdad0d9a5e05fb7 127.0.0.1:6381@16381 master - 0 1544091670247 3 connected 10923-16383

控制台信息显示:当前集群中存在3个主节点和3个从节点,虚拟槽的分配是0-5460、5461-10922、10923-16383 说明我们集群已经搭建完成。
至此,Redis Cluster集群就搭建完成了。

注意:

  1. 如果想重新创建集群,需要登录到每个节点,执行flushdb,然后执行cluster reset,重启节点;
  2. 如果要批量杀掉Redis进程,可以使用pkill redis-server命令;
  3. 如果redis开启了密码认证,则需要在redis.conf中增加属性 : masterauth yourpassword
  4. Redis开启密码认证后,在集群操作时问题会比较多,因此建议不要开启密码认证,搭配使用防火墙保证Redis的安全。

Redis Cluster 数据存储及异常

客户端在连接 redis cluster 的时候,可以将数据提交到任意一个redis cluster节点上,如果存储该数据的槽不在这个节点上,则返回给客户端moved异常,客户端通过moved异常,永久的将请求转移到目标节点,如下图所示。

通过moved异常,客户端可以知道目标节点并重新提交数据,但是这种情形效率不算高,那怎么解决这个问题的呢?

redis客户端JedisCluster怎么解决这个问题的。

  1. 初始化时从集群中选一个可运行节点,使用cluster slots初始化槽和节点映射。
  2. 将cluster slots的结果映射到本地,为每个节点创建JedisPool。
  3. 准备执行命令。

现在我们来实际看下这个异常:
首先来看下redis cluster的节点信息,执行命令redis-cli cluster nodes

[root@192.168.118.15 ~]#redis-cli -h 127.0.0.1 -p 6379
127.0.0.1:6379> cluster nodes
fd583297b826fc92bc872d5a3a6e8bfda30a5eda 127.0.0.1:6382@16382 slave 7bb6e7b6b77db35a306ff932a8a70277763e3504 0 1544165240000 4 connected
a6d4cb574131b82d95f58c92c9fe5389dcb16f59 127.0.0.1:6383@16383 slave a798db2f4e6a756606677bf82b0488c517402412 0 1544165239936 5 connected
7bb6e7b6b77db35a306ff932a8a70277763e3504 127.0.0.1:6379@16379 myself,master - 0 1544165240000 1 connected 0-5460
d984d502c61d2b3d64b0100a0179642d92c9f95d 127.0.0.1:6384@16384 slave 292362ebc26df9920de8e8c19fdad0d9a5e05fb7 0 1544165241941 6 connected
a798db2f4e6a756606677bf82b0488c517402412 127.0.0.1:6380@16380 master - 0 1544165239000 2 connected 5461-10922
292362ebc26df9920de8e8c19fdad0d9a5e05fb7 127.0.0.1:6381@16381 master - 0 1544165241000 3 connected 10923-16383

可以看到使用的是3主3从的配置,虚拟槽的分配是0-5460、5461-10922、10923-16383,我们来演示下这个异常。。

127.0.0.1:6379> set a b
(error) MOVED 15495 127.0.0.1:6381

可以看到,key为a的时候应该将数据插入到15495的槽内。但是15495这个槽是分配在端口号为6381的这个节点上。当尝试插入操作的时候返回了moved异常,异常信息包括目标节点和槽的信息。
要直接通过redis-cli 登录插入可以使用 -c 选项,-c为以集群模式登录

[root@192.168.118.15 ~]#redis-cli -h 127.0.0.1 -p 6379 -c
127.0.0.1:6379> set a b
-> Redirected to slot [15495] located at 127.0.0.1:6381
OK
127.0.0.1:6381> keys *
1) "a"

【消息机制】

redis cluster 集群中通过消息来进行通信。消息共有以下5种:

meet消息:发送者会向接受者发送cluster meet命令,请求接受者将发送者加入到集群中。所谓的无中心网络结构就是使用meet命令构建的。
ping消息:集群中的每个节点每秒钟都会从已知节点列表选举出5个节点,然后从这5个节点中选中一个最长时间没有发送ping消息的节点作为目标节点来发送ping消息,来检测目标节点是否处于在线状态。
pong消息:接受者接受到发送者发送的meet消息或者ping消息后,会回复pong消息,用于确认消息已经到达。另外,pong消息也可以用于刷新接收者对发送者的信息,例如故障转移后,从节点会向集群中发送pong消息,用于告知从节点已经升级为主节点。
fail消息:fail消息用于通知将某个节点置为下线状态。例如节点A认为节点B已下线,节点A会向集群中发送一条fail消息,接受到这条消息的节点会将节点B标记为已 下线。
publish消息:当某个节点收到publish命令后,会向集群中发送一条publish消息。

【故障检测】

集群中的每个节点都会定期地向集群中其它节点发送ping消息,以此来检测对方是否在线。如果在规定时间内没有收到pong回复。则认为目标节点标记为疑似下线(PFAIL)。
如果集群中的半数异常(大于等于N/2 + 1)的主节点认为某个节点A疑似下线(PFAIL),那么这个节点A将被标记为已下线(FAIL)。将节点标记A为已下线的节点会向集群发送一条关于节点A显现的消息,所有收到这条F消息的节点都会立即将主节点A标记为已下线。
举个例子,在下图所示中,主节点7002和主节点7003都认为主节点7000进入了下线状态。并且主节点7001也认为主节点7000进入了下线状态。综合起来,在集群中4个主节点里面,有3个都将主节点7000标记为下线。所以主节点7001会将7000节点标记为已下线。并向集群中广播一条关于主节点7000的FAIL消息,如下图所示。

【故障转移】

当一个从节点发现自己正在复制的主节点进入了已下线时,从节点将开始对已下线的主节点进行故障转移操作,以下是故障转移的执行步骤:

  1. 下线的主节点的所有从节点里面会进行选举,选举出一个新的主节点;
  2. 被选中的从节点会执行 slave no one命令,成为新的主节点;
  3. 新的主节点会撤销所有对已下线主节点的槽指派,并将这些槽指派给自己;
  4. 新的主节点向集群广播一条pong消息,这条pong消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点处理的槽。
  5. 新的主节点开始接受和自己负责处理的槽有关的命令请求,故障转移操作完成。

模拟redis cluster 节点服务挂掉后,slave切换为主节点

[root@192.168.118.15 ~]#redis-cli -h 127.0.0.1 -p 6379 -c
127.0.0.1:6379> cluster nodes
fd583297b826fc92bc872d5a3a6e8bfda30a5eda 127.0.0.1:6382@16382 slave 7bb6e7b6b77db35a306ff932a8a70277763e3504 0 1544166906000 4 connected
a6d4cb574131b82d95f58c92c9fe5389dcb16f59 127.0.0.1:6383@16383 slave a798db2f4e6a756606677bf82b0488c517402412 0 1544166907000 5 connected
7bb6e7b6b77db35a306ff932a8a70277763e3504 127.0.0.1:6379@16379 myself,master - 0 1544166904000 1 connected 0-5460
d984d502c61d2b3d64b0100a0179642d92c9f95d 127.0.0.1:6384@16384 slave 292362ebc26df9920de8e8c19fdad0d9a5e05fb7 0 1544166905995 6 connected
a798db2f4e6a756606677bf82b0488c517402412 127.0.0.1:6380@16380 master - 0 1544166906000 2 connected 5461-10922
292362ebc26df9920de8e8c19fdad0d9a5e05fb7 127.0.0.1:6381@16381 master - 0 1544166907998 3 connected 10923-16383

集群中3个master、3个slave 状态都为:connected

[root@192.168.118.15 ~]#redis-cli -h 127.0.0.1 -p 6380 shutdown  # down掉其中一个master节点

127.0.0.1:6379> cluster nodes
fd583297b826fc92bc872d5a3a6e8bfda30a5eda 127.0.0.1:6382@16382 slave 7bb6e7b6b77db35a306ff932a8a70277763e3504 0 1544166994224 4 connected
a6d4cb574131b82d95f58c92c9fe5389dcb16f59 127.0.0.1:6383@16383 master - 0 1544166992000 7 connected 5461-10922    # 为做 6380 的从节点已经切换为master
7bb6e7b6b77db35a306ff932a8a70277763e3504 127.0.0.1:6379@16379 myself,master - 0 1544166993000 1 connected 0-5460
d984d502c61d2b3d64b0100a0179642d92c9f95d 127.0.0.1:6384@16384 slave 292362ebc26df9920de8e8c19fdad0d9a5e05fb7 0 1544166992218 6 connected
a798db2f4e6a756606677bf82b0488c517402412 127.0.0.1:6380@16380 master,fail - 1544166962530 1544166959000 2 disconnected    # 状态为: fail
292362ebc26df9920de8e8c19fdad0d9a5e05fb7 127.0.0.1:6381@16381 master - 0 1544166993220 3 connected 10923-16383

注意:如果集群超过半数以上(6个服务down超过3个服务)master挂掉,无论是否有slave,集群进入fail状态.

python 连接 Redis Cluster 方式

#!/usr/bin/python
# rediscluster包需要python安装 pip install redis-py-cluster

from rediscluster import StrictRedisCluster


redis_nodes = [{'host': '192.168.118.15', 'port': 6379},
               {'host': '192.168.118.15', 'port': 6380},
               {'host': '192.168.118.15', 'port': 6381},
               {'host': '192.168.118.15', 'port': 6382},
               {'host': '192.168.118.15', 'port': 6383},
               {'host': '192.168.118.15', 'port': 6384}]

redisconn = StrictRedisCluster(startup_nodes=redis_nodes)

#redisconn.set('name', 'hkey')    # 插入数据
#redisconn.set('age', 20)    # 插入数据
#for i in range(10000):    # 循环插入数据
#    redisconn.set(i, 'Test')
print(redisconn.get('name'))    # 获取数据
print(redisconn.get('age'))        # 获取数据

或者通过 Redis Desktop Manager 连接:

原文地址:https://www.cnblogs.com/hukey/p/10083984.html