Reids 6.x——集群环境部署

集群环境部署

1、主从复制

主从复制也叫主从模式,当用户向Master写入数据时,Master通过Redis同步机制将数据文件发送至Slave,Slave也会通过Redis同步机制将数据文件发送至Master以确保数据一致,从而实现Redis的主从复制。如果Master和Slave之间的连接中断,Slave可以自动重连Master,但是连接成功后,将自动执行一次完全同步。

配置主从复制后,Master可以负责读写服务,Slave只负责读服务。Redis复制在Master这一端是非阻塞的,也就是说在和Slave同步数据的时候,Master仍然可以执行客户端的命令而不受其影响。

1.主从复制的特点

  • 同一个Master可以拥有多个Slave。
  • Master下的Slave还可以接受同一架构中其他Slave的连接与同步请求,实现数据的级联复制,即Master→Slave→Slave模式。
  • Master以非阻塞的方式同步数据至Slave,这将意味着Master会继续处理一个或多个Slave的读写请求。
  • 主从复制不会阻塞Master,当一个或多个Slave与Master进行初次同步数据时,Master可以继续处理客户端发来的请求。
  • 主从复制具有可扩展性,即多个Slave专门提供只读查询与数据的冗余,Master专门提供写操作。
  • 通过配置禁用Master数据持久化机制,将其数据持久化操作交给Slave完成,避免在Master中有独立的进程来完成此操作。

2.主从复制的优势

  • 避免Redis单点故障。
  • 做到读写分离,构建读写分离架构,满足读多写少的应用场景。

1.1、Redis主从复制原理

当启动一个Slave进程后,它会向Master发送一个SYNC命令,请求同步连接。无论是第一次连接还是重新连接,Master都会启动一个后台进程,将数据快照保存到数据文件中,同时Master会记录所有修改数据的命令并将其缓存在数据文件中。

后台进程完成缓存操作后,Master就发送数据文件给Slave,Slave将数据文件保存到硬盘上,然后将其加载到内存中。接着Master就会把所有修改数据的命令发送给Slave。

若Slave出现故障导致宕机,那么恢复正常后会自动重新连接。Master收到Slave的连接请求后,将其完整的数据文件发送给Slave。如果Mater同时收到多个Slave发来的同步请求,那么Master只会在后台启动一个进程保存数据文件,然后将其发送给所有的Slave,确保Slave正常。

关于Redis的安装与配置这里不再重复。Redis主从复制环境使用的服务器资源如表所示,将Redis安装在3台服务器上,3台服务器的操作系统都是CentOS 7。

1.2、Redis主从复制安装过程

1.Master操作

在Redis主服务器上的redis.conf配置文件中修改bind字段,将以下内容:

bash 复制代码
bind 127.0.0.1

修改为Master的主机IP地址。

bash 复制代码
bind 127.0.0.1 192.168.11.10

如果Redis主服务器只绑定了127.0.0.1,那么跨服务器IP地址的访问就会失败,也就是只有本机才能访问,外部请求会被过滤,这是由Linux的网络安全策略管理的。如果绑定的IP地址只是192.168.11.10,那么本机通过localhost和127.0.0.1,或者直接输入命令redis-cli登录本机Redis就会失败。所以跨服务器访问Redis,需要加上服务器IP地址才能被访问。

运行Redis服务。

bash 复制代码
$ redis-server /usr/local/redis/conf/redis.conf

2.Slave1操作

修改Redis的配置文件。

bash 复制代码
$ vi /usr/local/redis/conf/redis.conf

添加Master的IP地址与端口。

bash 复制代码
slaveof 192.168.11.10 6379

添加Mater的IP地址和端口时,中间用空格分隔,然后保存redis.conf配置文件。

运行Slave1(192.168.11.11)的Redis。

bash 复制代码
$ redis-server /usr/local/redis/conf/redis.conf

查看Slave1运行日志,如图所示。

3.Slave2操作

修改Redis的配置文件,添加Master的IP地址与端口。

bash 复制代码
$ vi /usr/local/redis/conf/redis.conf
slaveof 192.168.1.10 6379

添加Master的IP地址和端口时,中间用空格分隔,然后保存redis.conf配置文件。

运行Slave2(192.168.11.12)的Redis。

bash 复制代码
$ redis-server /usr/local/redis/conf/redis.conf

查看Slave2运行日志,如图所示。

结果与Slave1类似,只不过Slave2与Slave1(192.168.11.11:6379)建立连接,在同步数据时,Redis的主从级联复制便是这样:Master→Slave1→Slave2。

1.3、Redis测试主从复制关系

1.通过info replication命令查看节点角色

在主节点(192.168.11.10)输入info replication命令查看节点角色,会发现角色是Master,有两个从节点Slave1(192.168.11.11)和Slave2(192.168.11.12)​,如图6-4所示。

在info replication命令的返回信息中"slave0:ip=192.168.11.11,port=6379,state=online,offset=1681,lag=0"​,表示slave0是个从节点,使用的IP地址是192.168.11.11,端口是6379,状态是online(在线状态)​。这里的slave0对应上一节中配置的Slave1从节点,类似地,在返回信息中的Slave1对应上一节中配置的Slave2从节点。

在从节点(192.168.11.11)输入info replication命令查看节点角色,会发现节点角色是Slave,它的主节点IP地址是192.168.11.10,端口是6379,如图所示。

在从节点(192.168.11.12)输入info replication命令查看节点角色,也会发现节点角色是Slave,它的主节点IP地址是192.168.11.10,端口是6379,如图所示。

2.测试主从读写分离

在Master操作如下,由客户端验证同步结果。

bash 复制代码
$ redis-cli -h 192.168.1.10 -p 6379
192.168.11.10:6379> SET name xinping
OK
192.168.11.10:6379>

在Slave1验证同步结果。

bash 复制代码
$ /usr/local/redis/bin/redis-cli -h 192.168.11.11 -p 6379
192.168.11.11:6379> KEYS *
1) "name"
192.168.11.11:6379> GET name
"xinping"
192.168.11.11:6379>

在Slave2验证同步结果。

bash 复制代码
$ /usr/local/redis/bin/redis-cli -h 192.168.11.12 -p 6379
192.168.11.12:6379> KEYS *
1) "name"
192.168.11.12:6379> GET name
"xinping"
192.168.11.12:6379>

主从复制只能在主节点执行写操作,在从节点执行写操作会报异常"(error)READONLY You can't write against aread only replica."​,如图所示。

3.测试主节点宕机

本实例测试当主节点宕机时,两个从节点的角色是否会发生变化。

首先,在主节点使用shutdown命令,模拟计算机故障停止主节点的服务。

bash 复制代码
[root@localhost ~]# redis-cli -h 192.168.11.10 -p 6379
192.168.11.10:6379> shutdown

然后,在从节点使用info replication命令查看角色。从图中可以看出,当主节点宕机后,从节点的角色没有发生变化,不过master_link_status的状态变为down,意味着此时从节点执行读取命令,无法承担起主节点的任务,从节点只能执行读操作。

通过主从配置的实例,我们可以看出主节点只有一个,一旦主节点宕机之后,从节点无法承担起主节点的任务,那么整个系统也无法运行。如果主节点宕机之后,从节点能够自动变成主节点,那么问题就解决了,于是哨兵模式诞生了。

2、哨兵模式

2.1、灾备切换Sentinel的使用

Redis 2.6中开始提供了哨兵模式,到Redis 2.8以后的版本中该模式正式稳定。哨兵(Sentinel)进程监控Redis集群中Master主服务器工作的状态,在Master发生故障的时候,可以实现Master和Slave的切换,保证系统的高可用性。哨兵模式的出现是为了解决主从复制的缺点,其架构如图所示。

1.哨兵模式的基本概念

  • Master节点:主节点,Redis的主数据库,写入都在这个节点上。
  • Slave节点:从节点,Redis的从数据库,读取都在这个节点上。
  • Sentinel节点:哨兵节点,监控各个节点的状态。

基于哨兵模式的高可用架构如图所示。

在这个架构中,复制主要是将主节点的数据同步到从节点,这样做主要有以下两个原因。

  • 一旦主节点宕机了,从节点可以作为主节点的备份随时成为新的主节点。
  • 从节点可以作为主节点分担读的压力。

2.哨兵进程的作用

  1. 监控(Monitoring):哨兵进程会不断地检查Master和Slave是否运作正常。
  2. 提醒(Notification):当被监控的某个节点出现问题时,哨兵进程可以通过API向管理员或者其他应用程序发送通知。
  3. 自动故障迁移(Automatic Failover):当一个Master不能正常工作时,哨兵进程会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master,并让失效Master的其他Slave改为复制新的Master。当客户端试图连接失效的Master时,Redis集群也会向客户端返回新Master的地址,使得Redis集群可以使用现在的Master替换失效Master。Redis Sentinel故障转移架构如图所示。
  4. 配置提供者:在哨兵模式下,客户端在初始化时连接的是哨兵节点集合,从中获取主节点的信息。

3.部署技巧

  • 在生产环境中Sentinel节点不应该部署在一台物理"计算
  • 在生产环境中部署至少3个且奇数个Sentinel节点。

2.2、Redis Sentinel的安装与配置

配置一个(Master)和两个(Slave)​,并在一台服务器上部署Redis服务器和Sentinel实例。哨兵模式的实验环境如表所示。

Redis Sentinel的主从架构如图所示。

第1步:安装Redis。

(1)首先,安装gcc基础依赖包,使用如下命令。

bash 复制代码
$ yum install gcc-c++

(2)下载Redis压缩包。

bash 复制代码
$ wget http://download.redis.io/releases/redis-6.0.6.tar.gz

解压缩Redis压缩包。

bash 复制代码
$ tar -xzvf redis-6.0.6.tar.gz

进入解压缩后的目录。

bash 复制代码
$ cd redis-6.0.6/

使用make命令编译Redis源文件。

bash 复制代码
$ make

编译成功后,安装Redis。

bash 复制代码
$ make install PREFIX=/usr/local/redis

安装成功后,需要对Redis进行部署,把Redis的配置文件sentinel.conf复制到/usr/local/redis/conf目录下。

bash 复制代码
$ mkdir /usr/local/redis/conf
$ cp sentinel.conf /usr/local/redis/conf

(3)配置Redis的命令。

最后需要将Redis的命令所在目录添加到系统变量Path中,修改/etc/profile文件。

bash 复制代码
$ vi /etc/profile

在/etc/profile文件最后一行添加以下内容。

bash 复制代码
export PATH=$PATH:/usr/local/redis/bin

使用source命令使/etc/profile文件生效。

bash 复制代码
$ source /etc/profile

至此,Redis在Linux上的安装和配置就结束了。

第2步:主从节点的安装和配置。

在/usr/local下创建文件夹redis-sential,使用如下命令。

bash 复制代码
$ mkdir -p /usr/local/redis-sential
$ cd /usr/local/redis-sential/

(1)安装主节点。

建立配置目录。

bash 复制代码
$ mkdir -p /opt/soft/redis/data/
$ mkdir -p /var/run/

创建主节点的配置文件redis-7000.conf。

bash 复制代码
$ vi redis-7000.conf

在主节点的配置文件中添加以下内容。

bash 复制代码
port 7000
daemonize yes
pidfile /var/run/redis-7000.pid
logfile "7000.log"
dir "/opt/soft/redis/data/"

(2)创建从节点。

创建从节点的配置文件redis-7001.conf。

bash 复制代码
$ vi redis-7001.conf

在从节点的配置文件中添加以下内容。

bash 复制代码
port 7001
daemonize yes
pidfile /var/run/redis-7001.pid
logfile "7001.log"
dir "/opt/soft/redis/data/"
slaveof 127.0.0.1 7000

创建从节点的配置文件redis-7002.conf。

bash 复制代码
$ vi redis-7002.conf

在从节点的配置文件中添加以下内容。

bash 复制代码
port 7002
daemonize yes
pidfile /var/run/redis-7002.pid
logfile "7002.log"
dir "/opt/soft/redis/data/"
slaveof 127.0.0.1 7000

(3)快速启动节点。

启动主节点7000。

bash 复制代码
$ redis-server /usr/local/redis-sential/redis-7000.conf

查看是否连接了主节点7000。

bash 复制代码
[root@localhost redis-sential]# redis-cli -p 7000
127.0.0.1:7000> PING
PONG

启动两个从节点7001、7002。

bash 复制代码
$ redis-server /usr/local/redis-sential/redis-7001.conf
$ redis-server /usr/local/redis-sential/redis-7002.conf

查看Redis进程。

bash 复制代码
[root@localhost ~]# ps -ef | grep redis 
root       4356      1  0 16:56 ?        00:00:00 redis-server *:7000 
root       4582      1  0 17:09 ?        00:00:00 redis-server *:7001 
root       4596      1  0 17:09 ?        00:00:00 redis-server *:7002 
root       4615   4480  0 17:10 pts/1    00:00:00 grep --color=auto redis

查看主从复制的关系。

bash 复制代码
[root@localhost redis-sential]# redis-cli -p 7000 
127.0.0.1:7000> info replication 
# Replication 
role:master 
connected_slaves:2 
slave0:ip=127.0.0.1,port=7001,state=online,offset=168,lag=1 
slave1:ip=127.0.0.1,port=7002,state=online,offset=168,lag=0 
master_replid:85839c786b670a193462c2f77d043032b71a0c5c 
master_replid2:0000000000000000000000000000000000000000 
master_repl_offset:168 
second_repl_offset:-1 
repl_backlog_active:1 
repl_backlog_size:1048576 
repl_backlog_first_byte_offset:1 
repl_backlog_histlen:168

从以上信息可以看出主节点7000的角色是Master,有两个从节点Slave0和Slave1,它们占用的端口分别是7001和7002。

第3步:配置开启Sentinel监控主节点。

Sentinel是特殊的Redis,Sentinel主要负责监控故障转移和通知。Sentinel默认端口是26379。

复制sentinel.conf配置文件到指定目录。

bash 复制代码
$ cp /usr/local/redis/conf/sentinel.conf /usr/local/redis-sential

将sentinel.conf配置文件所有的空行和注释去掉。

bash 复制代码
$ cat sentinel.conf | grep -v "#" | grep -v "^$" > redis-sentinel-26379.conf

查看sentinel.conf配置文件发现所有的空行和注释都去掉了。

bash 复制代码
[root@localhost redis-sential]# cat redis-sentinel-26379.conf  
port 26379 
daemonize no 
pidfile /var/run/redis-sentinel.pid 
logfile "" 
dir /tmp 
sentinel monitor mymaster 127.0.0.1 6379 2 
sentinel down-after-milliseconds mymaster 30000 
sentinel parallel-syncs mymaster 1 
sentinel failover-timeout mymaster 180000 
sentinel deny-scripts-reconfig yes

然后再对redis-sentinel-26379.conf配置文件进行修改。

bash 复制代码
$ vi redis-sentinel-26379.conf

添加以下内容。

bash 复制代码
port 26379 
daemonize yes 
pidfile /var/run/redis-sentinel.pid 
logfile "26379.log" 
dir /opt/soft/redis/data 
sentinel monitor mymaster 127.0.0.1 7000 2 
sentinel down-after-milliseconds mymaster 30000 
sentinel parallel-syncs mymaster 1 
sentinel failover-timeout mymaster 180000 
sentinel deny-scripts-reconfig yes

使用以下命令启动Sentinel。

bash 复制代码
$ redis-sentinel redis-sentinel-26379.conf

查看Sentinel进程,可以看出已经启动了。

bash 复制代码
[root@localhost redis-sential]# ps -ef | grep redis-sentinel 
root       7045      1  0 20:32 ?        00:00:03 redis-sentinel *:26379 [sentinel] 
root       7440   2629  0 21:08 pts/0    00:00:00 grep --color=auto redis-sentinel

使用redis-cli命令连接到Sentinel节点。

bash 复制代码
$ redis-cli -p 26379

连接成功。

bash 复制代码
[root@localhost redis-sential]# redis-cli -p 26379 
127.0.0.1:26379> ping 
PONG

输入info sentinel命令会返回如下信息。

bash 复制代码
127.0.0.1:26379>info sentinel
# Sentinel 
sentinel_masters:1 
sentinel_tilt:0 
sentinel_running_scripts:0 
sentinel_scripts_queue_length:0 
sentinel_simulate_failure_flags:0 
master0:name=mymaster,status=ok,address=127.0.0.1:7000,slaves=2,sentinels=1

可以看到有一个Master和两个Slave,只有一个Sentinel。

还是查看redis-sentinel-26379.conf配置文件,在文件的最下面会发现多了4行内容,这是配置重写操作时产生的内容。

bash 复制代码
[root@localhost redis-sential]# cat redis-sentinel-26379.conf  
port 26379 
daemonize yes 
pidfile "/var/run/redis-sentinel.pid" 
logfile "26379.log" 
dir "/opt/soft/redis/data" 
sentinel myid 6c6fb93d92461803a7df349af5f1ba280c1c0a41 
sentinel deny-scripts-reconfig yes 
sentinel monitor mymaster 127.0.0.1 7000 2 
sentinel config-epoch mymaster 0 
sentinel leader-epoch mymaster 0 
# Generated by CONFIG REWRITE 
protected-mode no 
sentinel known-replica mymaster 127.0.0.1 7002 
sentinel known-replica mymaster 127.0.0.1 7001 
sentinel current-epoch 0

根据这个配置文件再生成两个配置文件。

(1)生成redis-sentinel-26380.conf配置文件。

bash 复制代码
$ cat sentinel.conf | grep -v "#" | grep -v "^$" > redis-sentinel-26380.conf 
$ vi redis-sentinel-26380.conf

添加以下内容。

bash 复制代码
port 26380 
daemonize yes 
pidfile /var/run/redis-sentinel.pid 
logfile "26380.log" 
dir /tmp 
sentinel monitor mymaster 127.0.0.1 7000 2 
sentinel down-after-milliseconds mymaster 30000 
sentinel parallel-syncs mymaster 1 
sentinel failover-timeout mymaster 180000 
sentinel deny-scripts-reconfig yes

(2)生成redis-sentinel-26381.conf配置文件。

bash 复制代码
$ cat sentinel.conf | grep -v "#" | grep -v "^$" > redis-sentinel-26381.conf 
$ vi redis-sentinel-26381.conf

添加以下内容。

bash 复制代码
port 26381 
daemonize yes 
pidfile /var/run/redis-sentinel.pid 
logfile "26381.log"
dir /tmp 
sentinel monitor mymaster 127.0.0.1 7000 2 
sentinel down-after-milliseconds mymaster 30000 
sentinel parallel-syncs mymaster 1 
sentinel failover-timeout mymaster 180000 
sentinel deny-scripts-reconfig yes

使用以下命令启动两个Sentinel节点。

bash 复制代码
$ redis-sentinel redis-sentinel-26380.conf 
$ redis-sentinel redis-sentinel-26381.conf

查看Sentinel节点的进程。

bash 复制代码
[root@localhost redis-sential]# ps -ef | grep  redis-sentinel 
root       3215      1  0 00:03 ?        00:00:00 redis-sentinel *:26379 [sentinel] 
root       3258      1  0 00:06 ?        00:00:00 redis-sentinel *:26380 [sentinel] 
root       3263      1  0 00:06 ?        00:00:00 redis-sentinel *:26381 [sentinel] 
root       3276   3050  0 00:07 pts/0    00:00:00 grep --color=auto redis-sentinel

使用redis-cli命令连接到一个Sentinel节点。

bash 复制代码
$ redis-cli -p 26381

查看节点信息。

bash 复制代码
[root@localhost redis-sential]# redis-cli -p 26381 
127.0.0.1:26381> info sentinel 
# Sentinel 
sentinel_masters:1 
sentinel_tilt:0 
sentinel_running_scripts:0 
sentinel_scripts_queue_length:0 
sentinel_simulate_failure_flags:0 
master0:name=mymaster,status=ok,address=127.0.0.1:7000,slaves=2,sentinels=3

可以看到Sentinel有3个,至此Sentinel已经配置完成。

使用redis-cli命令连接主节点7000进行测试。

bash 复制代码
[root@localhost redis-sential]# redis-cli -p 7000 
127.0.0.1:7000> SET username xinping 
OK 
127.0.0.1:7000> SET address beijing 
OK

再连接从节点7001。

2.3、测试主从切换

1.查看Redis集群信息

在Redis客户端使用info replication命令查看Redis集群信息。

bash 复制代码
[root@localhost redis-sential]# redis-cli -p 7000 
127.0.0.1:7000> info replication 
# Replication 
role:master 
connected_slaves:2 
slave0:ip=127.0.0.1,port=7001,state=online,offset=503925,lag=0 
slave1:ip=127.0.0.1,port=7002,state=online,offset=503925,lag=0 
master_replid:5ad27de305049aad423d77c71c79ccf72615af42 
master_replid2:0000000000000000000000000000000000000000 
master_repl_offset:503925 
second_repl_offset:-1 
repl_backlog_active:1 
repl_backlog_size:1048576 
repl_backlog_first_byte_offset:1 
repl_backlog_histlen:503925

2.查看进程信息

使用ps-ef|grep redis命令查看进程信息。

bash 复制代码
[root@localhost redis-sential]# ps -ef | grep redis 
root       3191      1  0 00:02 ?        00:00:03 redis-server *:7000 
root       3196      1  0 00:02 ?        00:00:03 redis-server *:7001 
root       3202      1  0 00:02 ?        00:00:03 redis-server *:7002 
root       3215      1  0 00:03 ?        00:00:05 redis-sentinel *:26379 [sentinel] 
root       3258      1  0 00:06 ?        00:00:04 redis-sentinel *:26380 [sentinel] 
root       3263      1  0 00:06 ?        00:00:04 redis-sentinel *:26381 [sentinel] 
root       3696   3050  0 00:48 pts/0    00:00:00 grep --color=auto redis

可以看出Redis的主节点占用的端口为3191、3196和3202,可以使用kill命令结束一个主节点的进程。

使用kill命令结果一个主节点的进程。

bash 复制代码
$ kill -9 3191

3.查看主节点

使用redis-cli命令连接到7001节点。

bash 复制代码
[root@localhost data]# redis-cli -p 7001 
127.0.0.1:7001> info replication 
# Replication 
role:master 
connected_slaves:1 
slave0:ip=127.0.0.1,port=7002,state=online,offset=589803,lag=0 
master_replid:dcf84d35e3474035e74f300f351c02aa404efc65 
master_replid2:5ad27de305049aad423d77c71c79ccf72615af42 
master_repl_offset:589950 
second_repl_offset:573709 
repl_backlog_active:1 
repl_backlog_size:1048576 
repl_backlog_first_byte_offset:1 
repl_backlog_histlen:589950

从上面可以看出主节点变为7002。

通过哨兵模式的配置,我们可以看出哨兵模式是基于主从模式的,哨兵模式具有主从模式的所有优点。哨兵模式是主从模式的升级,实现了自动化的故障恢复。但哨兵模式的缺点也很明显,Redis较难实现在线扩容,在集群容量达到上限时在线扩容会变得很复杂。实现哨兵模式的配置也不简单,甚至有些烦琐,于是就有了Redis集群。Redis集群是官方的Redis集群实现。

3、Redis集群

Redis集群是一个由多个主从节点组成的分布式服务器群,它具有复制、高可用和分片特性。Redis集群将所有数据存储区域划分为16384个槽(Slot)​,每个节点负责一部分槽,槽的信息存储于每个节点中。Redis集群要将每个节点设置成集群模式,它没有中心节点,可水平扩展,它的性能和高可用性均优于主从模式和哨兵模式,而且集群配置非常简单。Redis集群架构如图所示。

从Redis集群架构中可以很容易地看出,首先将数据根据散列规则分配到6个槽中,然后根据循环冗余校验(Cyclic Redundancy Check,CRC)算法和取模算法将6个槽分别存储到3个不同的Master节点中,每个Master节点又配套部署了一个Slave节点,当一个Master节点出现问题后,Slave节点可以顶上。相较于哨兵模式,这种方案的优点在于提高了读写的并发率,分散了I/O,在保障高可用性的前提下提高了性能。

3.1、Redis集群环境

Redis集群在物理结构上是由集群上的多个节点构成的,这些节点分为两类,一类叫"主节点"​,另一类叫"从节点"​。

Redis集群节点要求如下。

  • 主节点不能少于总节点的一半。
  • 主节点至少要有3个。

一个Redis集群正常工作至少需要3个主节点且不能少于总节点的一半,本集群环境使用一台节点服务器,在这台服务器开启6个Redis实例,每个Redis实例占用一个端口,模拟3个主节点和3个从节点环境,组成一个Redis集群。本书使用一台服务器部署6个Redis实例,也可以多台服务器部署Redis集群,只修改Redis配置文件redis.conf的IP地址就可以了。本集群实验采用三主三从模式,每个主节点处理各自的数据,提供读写能力,每个从节点异步复制主节点的数据。Redis 5集群的实验环境如表所示。

为了方便配置Redis集群,本书以root用户登录各Linux服务器。

3.2、开始Redis集群搭建

第1步:安装Redis。

(1)安装gcc基础依赖包,使用如下命令。

bash 复制代码
$ yum install gcc-c++

(2)下载Redis压缩包。

bash 复制代码
$ wget http://download.redis.io/releases/redis-6.0.6.tar.gz

解压缩Redis压缩包。

bash 复制代码
$ tar -xzvf redis-5.0.5.tar.gz

进入解压缩后的目录。

bash 复制代码
$ cd redis-6.0.6/

使用make命令编译Redis源文件。

bash 复制代码
$ make

编译成功后,安装Redis。

bash 复制代码
$ make install PREFIX=/usr/local/redis

安装成功后,需要对Redis进行部署,把Redis的配置文件redis.conf复制到/usr/local/redis/conf目录下。

bash 复制代码
$ mkdir /usr/local/redis/conf
$ cp redis.conf /usr/local/redis/conf

(3)配置Redis的命令。

最后需要将Redis的命令所在目录添加到系统变量Path中,修改/etc/profile文件。

bash 复制代码
$ vi /etc/profile

在/etc/profile文件最后一行添加以下内容。

bash 复制代码
export PATH=$PATH:/usr/local/redis/bin

然后使用source命令使/etc/profile文件立即生效。

bash 复制代码
$ source /etc/profile

至此,Redis在Linux上的安装和配置就结束了。

第2步:在/usr/local下创建文件夹redis-cluster,然后在其下创建如下6个文件夹。

bash 复制代码
$ mkdir -p /usr/local/redis-cluster
$ cd /usr/local/redis-cluster/
$ mkdir 8001 8002 8003 8004 8005 8006

第3步:把之前的redis.conf配置文件复制到8001目录下。

bash 复制代码
$ cp /usr/local/redis/conf/redis.conf /usr/local/redis-cluster/8001

使用vi命令修改redis.conf配置文件。

bash 复制代码
$ vi /usr/local/redis-cluster/8001/redis.conf

修改redis.conf配置文件中的以下配置项,redis.conf配置文件可以参考本书的配套实例代码"Redis\Chapter06\Redis6集群参考配置文件\redis-cluster\8001\redis.conf"​。

(1)daemonize yes:开启Redis的守护进程。开启Redis的守护进程后,Redis会在后台一直运行,除非手动输入kill命令结束进程。

(2)port 8001:分别对每个节点计算机的端口号进行设置。

(3)dir/usr/local/redis-cluster/8001/:设定数据文件存放位置,必须要指定不同的目录位置,否则会丢失数据。

(4)cluster-enabled yes:启动集群模式。

(5)cluster-config-file nodes-8001.conf:集群节点信息文件,这里nodes-8001.conf最好和端口对应。

(6)cluster-node-timeout 5000:集群节点的超时时限,单位为毫秒。

(7)bind 192.168.11.15:修改为主机的IP地址,默认IP地址为127.0.0.1,需要修改为其他节点计算机可访问的IP地址,否则创建集群时无法访问对应计算机的端口,无法创建集群。

(8)protected-mode no:关闭保护模式。

(9)appendonly yes:开启AOF持久化。

如果要设置密码需要增加如下配置。

(10)requirepass xxx:设置Redis的访问密码(本例使用xxx代替密码,读者可根据实际情况自行设置)​。

(11)masterauth xxx:设置集群节点间的访问密码(本例使用xxx代替密码,读者可根据实际情况自行设置)​,与(10)中设置的密码一致。

第4步:把修改后的redis.conf配置文件复制到8002、8003、8004、8005和8006目录下,修改(2)​(3)​(5)里的端口。

第3步已经完成了一个Redis节点的配置,接下来就是机械化地再完成另外5个节点的配置。其实可以这么做:把8001实例的redis.conf配置文件复制到另外5个文件夹中,并修改redis.conf配置文件中所有和端口相关的信息,其实就是port,dir和cluster-config-file配置项的端口信息。

bash 复制代码
$ cd /usr/local/redis-cluster/8001
$ cp redis.conf /usr/local/redis-cluster/8002
$ cp redis.conf /usr/local/redis-cluster/8003
$ cp redis.conf /usr/local/redis-cluster/8004
$ cp redis.conf /usr/local/redis-cluster/8005
$ cp redis.conf /usr/local/redis-cluster/8006

第5步:分别启动6个Redis节点,然后检查Redis节点是否启动成功。

bash 复制代码
$ redis-server /usr/local/redis-cluster/8001/redis.conf
$ redis-server /usr/local/redis-cluster/8002/redis.conf
$ redis-server /usr/local/redis-cluster/8003/redis.conf
$ redis-server /usr/local/redis-cluster/8004/redis.conf
$ redis-server /usr/local/redis-cluster/8005/redis.conf
$ redis-server /usr/local/redis-cluster/8006/redis.conf

执行启动6个Redis节点命令的返回结果如图所示。

使用ps-ef|grep redis命令查看Redis节点是否启动成功。从下图可以看出6个Redis节点已经全部启动成功了。

使用命令一个个启动Redis节点比较麻烦,我们可以使用脚本的方式启动Redis节点,使用以下命令创建Redis集群启动脚本(startRedisCluster.sh)​。

bash 复制代码
$ touch startRedisCluster.sh
$ chmod +x startRedisCluster.sh

使用vi startRedisCluster.sh命令修改startRedisCluster.sh脚本,添加以下内容。

bash 复制代码
redis-server /usr/local/redis-cluster/8001/redis.conf
redis-server /usr/local/redis-cluster/8002/redis.conf
redis-server /usr/local/redis-cluster/8003/redis.conf
redis-server /usr/local/redis-cluster/8004/redis.conf
redis-server /usr/local/redis-cluster/8005/redis.conf
redis-server /usr/local/redis-cluster/8006/redis.conf

使用以下命令启动脚本。

bash 复制代码
$ ./startRedisCluster.sh

第6步:使用redis-cli命令创建Redis集群,如图6-16所示。

bash 复制代码
$ redis-cli --cluster create --cluster-replicas 1 192.168.11.15:8001 192.168.11.
15:8002 192.168.11.15:8003 192.168.11.15:8004 192.168.11.15:8005 192.168.11.15:8006

使用redis-cli命令创建Redis集群使用的参数--cluster-replicas表示主节点和从节点的比例,当参数--cluster-replicas为1时,表示创建Redis集群时一个主节点需要有一个从节点。

按照提示"Can I set the above configuration?​"输入yes。

bash 复制代码
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 192.168.11.15:8001) 
M: fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001 
  slots:[0-5460] (5461 slots) master 
  1 additional replica(s) 
S: 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004 
  slots: (0 slots) slave 
  replicates fb8600a4f020daeebd85a64369a9aa04b38a7d39 
M: 12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002 
  slots:[5461-10922] (5462 slots) master 
  1 additional replica(s) 
M: 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003 
  slots:[10923-16383] (5461 slots) master 
  1 additional replica(s) 
S: 0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006 
  slots: (0 slots) slave 
  replicates 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 
S: 7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005 
  slots: (0 slots) slave 
  replicates 12904463a6c7caa958085e008ad0324213883811 
[OK] All nodes agree about slots configuration. 
>>> Check for open slots... 
>>> Check slots coverage... 
[OK] All 16384 slots covered.

以上是创建的Redis集群信息,可以看出每创建一个Redis主节点就创建一个Redis从节点。上述信息可以转换为表格形式,如表所示。

Redis集群的主从节点关系如图6-13所示,图中Redis集群有三个主节点和三个从节点,一个主节点对应一个从节点,形成一对一的对应关系,如图所示。

第7步:验证Redis集群。

(1)使用redis-cli命令连接Redis集群节点,实例如下。

bash 复制代码
$ redis-cli -c -a 密码 -h 192.168.11.15 -p 8001

redis-cli命令的参数-a表示访问Redis服务器密码,-c表示连接Redis集群,-h表示Redis集群节点的IP地址,-p表示Redis集群节点的端口号。如果Redis集群没有设置密码,可以省略参数-a。

可以使用以下任意一条命令连接Redis集群中的某个节点。

bash 复制代码
$ redis-cli -c -h 192.168.11.15 -p 8001 
$ redis-cli -c -h 192.168.11.15 -p 8002 
$ redis-cli -c -h 192.168.11.15 -p 8003 
$ redis-cli -c -h 192.168.11.15 -p 8004 
$ redis-cli -c -h 192.168.11.15 -p 8005 
$ redis-cli -c -h 192.168.11.15 -p 8006 

例如,使用命令redis-cli-c-h 192.168.11.15-p 8001访问Redis集群。

bash 复制代码
[root@localhost 8006]# redis-cli -c -h 192.168.11.15 -p 8001 
192.168.11.15:8001> SET name xinping 
-> Redirected to slot [5798] located at 192.168.11.15:8002 
OK 
192.168.11.15:8002> get name 
"xinping"

使用SET命令后,进入了端口为8002的Redis节点,进行了跳转重定向(Redirected)​。

(2)测试Redis集群是否正常。

使用cluster info命令查看Redis集群信息,返回值"cluster_known_nodes:6"表示当前Redis集群中共有6个Redis节点。

bash 复制代码
192.168.11.15:8001> 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:9036 
cluster_stats_messages_pong_sent:9029 
cluster_stats_messages_sent:18065 
cluster_stats_messages_ping_received:9024 
cluster_stats_messages_pong_received:9036 
cluster_stats_messages_meet_received:5 
cluster_stats_messages_received:18065

使用cluster nodes命令查看Redis集群节点列表,可以看出整个Redis集群含有3个主节点和3个从节点。

bash 复制代码
192.168.11.15:8001> cluster nodes 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 slave  
fb8600a4f020daeebd85a64369a9aa04b38a7d39 0 1598792307000 1 connected 
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 master -  
0 1598792309022 2 connected 5461-10922 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 myself,master -  
0 1598792307000 1 connected 0-5460 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master -  
0 1598792307274 3 connected 10923-16383 
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave  
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 0 1598792307478 3 connected 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave  
12904463a6c7caa958085e008ad0324213883811 0 1598792308506 2 connected

至此,Redis集群环境搭建完毕。

(3)使用redis-cli命令关闭Redis集群节点,实例如下。

bash 复制代码
$ redis-cli -a xxx -c -h 192.168.11.15 -p 8001 shutdown

在本例中可以使用以下命令关闭6个Redis集群节点。

bash 复制代码
$ redis-cli -c -h 192.168.11.15 -p 8001 shutdown 
$ redis-cli -c -h 192.168.11.15 -p 8002 shutdown 
$ redis-cli -c -h 192.168.11.15 -p 8003 shutdown 
$ redis-cli -c -h 192.168.11.15 -p 8004 shutdown 
$ redis-cli -c -h 192.168.11.15 -p 8005 shutdown 
$ redis-cli -c -h 192.168.11.15 -p 8006 shutdown

在此做一个实验,使用以下命令关闭端口为8001的Redis集群节点。

bash 复制代码
$ redis-cli -c -h 192.168.11.15 -p 8001 shutdown

再查看Redis进程,会发现端口为8001的Redis进程已经销毁。

bash 复制代码
[root@localhost ~]# ps -ef | grep redis 
root      16478      1  0 20:44 ?        00:00:01 redis-server 192.168.11.15:8001 [cluster] 
root      16484      1  0 20:44 ?        00:00:01 redis-server 192.168.11.15:8002 [cluster] 
root      16490      1  0 20:44 ?        00:00:01 redis-server 192.168.11.15:8003 [cluster] 
root      16496      1  0 20:44 ?        00:00:01 redis-server 192.168.11.15:8004 [cluster] 
root      16502      1  0 20:44 ?        00:00:01 redis-server 192.168.11.15:8005 [cluster] 
root      16508      1  0 20:44 ?        00:00:01 redis-server 192.168.11.15:8006 [cluster] 
root      16688  16645  0 20:58 pts/5    00:00:00 redis-cli -c -h 192.168.11.15 -p 8001 
root      16740  16400  0 21:01 pts/4    00:00:00 grep --color=auto redis

Redis客户端在连接上端口为8002的Redis集群节点后,查看Redis集群节点信息,会发现端口为8001的Redis集群节点的状态为"disconnected"​,表示这个集群节点已经关闭。

bash 复制代码
[root@localhost ~]# redis-cli -c -h 192.168.11.15 -p 8002 
192.168.11.15:8002> cluster nodes
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave   1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 0 1598792578903 3 connected 
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 myself,master - 0 1598792576000 2 connected 5461-10922 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 master -  0 1598792576550 7 connected 0-5460 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 master,fail - 1598792556868 1598792554304 1 disconnected 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master -  0 1598792578000 3 connected 10923-16383 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave  12904463a6c7caa958085e008ad0324213883811 0 1598792576860 2 connected

如果想要打开端口为8001的Redis集群节点,需要使用如下命令。

bash 复制代码
$ redis-server /usr/local/redis-cluster/8001/redis.conf 

3.3、Redis集群代理

集群代理(Cluster Proxy)是Redis 6的新特性。Redis集群代理(Redis Cluster Proxy)允许Redis客户端不需要知道集群中的具体节点个数和主从身份,直接通过集群代理访问集群。对于客户端来说,通过集群代理访问集群就和访问单机的Redis服务器一样,可以解除很多集群的使用限制。Redis集群代理架构如图所示。

Redis集群代理使用的服务器资源如表所示。使用上一节已经配置好的Redis集群环境,将Redis集群代理安装在CentOS 7操作系统下。

Redis集群代理目前的最新版本(截至2020年8月17日)是1.0-beta2,是测试版本,包含相对较多的漏洞,请谨慎在生产环境下使用,期待后续有稳定版本推出。

以root用户登录Linux服务器。使用Redis集群代理的实例如下。

1.安装Redis集群代理

首先,使用如下命令安装gcc基础依赖包。

bash 复制代码
$ yum -y install gcc-c++

为了编译Redis Cluster Proxy1.0-beta2源码还需要使用devtoolset命令升级gcc。gcc版本必须在4.9以上。

bash 复制代码
$ yum -y install centos-release-scl 
$ yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils 
$ scl enable devtoolset-9 bash 
$ echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile

安装完devtoolset后,需要输入scl enable devtoolset-9bash命令来启动devtoolset。启动devtoolset的命令仅针对本次会话有效,若重新登录Linux,需要再次使用scl命令启动devtoolset。

若要使devtoolset长期有效,需要输入echo"source/opt/rh/devtoolset-9/enable">>/etc/profile命令。

(2)下载、编译、安装和配置Redis集群代理。

然后安装git。git是一个分布式版本控制系统。

bash 复制代码
$ yum install git

建立下载目录/upload,并在这个目录下使用git下载最新版本的Redis Cluster Proxy源码包。

bash 复制代码
$ mkdir /upload 
$ cd /upload 
$ git clone https://github.com/artix75/redis-cluster-proxy

下载完成后,进入创建的redis-cluster-proxy目录。

bash 复制代码
$ cd redis-cluster-proxy

使用make命令安装Redis Cluster Proxy。

bash 复制代码
$ make PREFIX=/usr/local/redis_cluster_proxy install

make命令的参数PREFIX要大写,代表安装路径。执行make命令后,Redis Cluster Proxy的可执行命令会被自动复制到/usr/local/redis_cluster_proxy/bin目录下,这样执行Redis Cluster Proxy命令时,就不用输入完整路径了。

安装成功后,需要对Redis Cluster Proxy进行部署。把它的配置文件proxy.conf复制到/usr/local/redis-cluster-proxy/conf目录下。

bash 复制代码
$ mkdir -p /usr/local/redis_cluster_proxy/conf 
$ cd /upload/redis-cluster-proxy  
$ cp proxy.conf /usr/local/redis_cluster_proxy/conf

部署后,Redis集群代理的目录结构如图所示。

使用vi命令修改Redis集群代理的配置文件proxy.conf。

bash 复制代码
vi /usr/local/redis_cluster_proxy/conf/proxy.conf

修改proxy.conf配置文件中的以下配置项。

bash 复制代码
# 设置Redis集群代理端口,默认端口是7777,可以根据业务修改端口 
port 7777 
 
# 开启Redis的守护进程
daemonize yes 
 
# 设置Redis集群代理的日志文件 
logfile "/usr/local/redis_cluster_proxy/conf/redis-cluster-proxy.log" 
 
# 设置Redis集群的各个节点 
cluster 192.168.11.15:8001 
cluster 192.168.11.15:8002 
cluster 192.168.11.15:8003 
cluster 192.168.11.15:8004 
cluster 192.168.11.15:8005 
cluster 192.168.11.15:8006

最后,将Redis Cluster Proxy的可执行命令所在目录添加到系统参数PATH中,修改/etc/profile文件。

bash 复制代码
$ vi /etc/profile

在/etc/profile文件最后一行添加如下内容。

bash 复制代码
export PATH=$PATH:/usr/local/redis_cluster_proxy/bin

然后使用source命令使这个文件立即生效。

bash 复制代码
$ source /etc/profile

至此,Redis集群代理在Linux上的安装和配置就结束了。

2.启动和使用Redis集群代理

安装并配置好Redis Cluster Proxy后,启动Redis集群代理。

bash 复制代码
$ redis-cluster-proxy -c /usr/local/redis_cluster_proxy/conf/proxy.conf

redis-cluster-proxy命令的参数-c表示加载proxy.conf配置文件后启动Redis集群代理。执行启动Redis集群代理命令的返回结果如图所示,可以看出Redis集群代理已经成功启动。

执行ps-ef|grep redis命令,返回结果如图所示,可以看出Redis集群代理进程占用的端口是5855。

如果需要停止Redis集群代理,可以使用kill命令无条件终止Redis集群代理进程。

bash 复制代码
$ kill -9 5855

在Redis客户端使用如下命令连接到Redis集群代理。

bash 复制代码
$ redis-cli -h 192.168.11.15 -p 7777

与Redis集群连接方式不同,在Redis集群代理模式下,Redis客户端可以连接至Redis集群代理节点,而无须知道Redis集群自身的详细信息,操作Redis集群和操作单机Redis服务器是一样的,通过Redis集群代理访问并操作Redis集群的实例如图所示。

使用传统的Redis集群连接方式来查看上面SADD操作的结果如图所示。可以发现数据的确是写入Redis集群中不同的节点中了。

3.4、Redis集群特点

Redis集群方案采用的是散列分区的"虚拟槽分区"方式,槽范围是0~16383,共用16384(即214)个槽。每个节点会维护自身负责的槽及槽所映射的键值对数据。

所有key数据散列函数CRC16(key)%16384(可使用按位与操作优化为CRC16(key)&16383)被映射到槽内。具体来说,当需要在Redis集群中存储一个key-value对时,Redis先对key使用CRC16算法算出一个循环冗余校验码,然后将校验码对16384取余。这样每个key都会有一个0~16383的余数,从而对应一个槽。Redis会根据数量大致均等的原则将槽映射到不同的节点。例如,有3个主节点时,每个节点大致负责5500个槽的读写。Redis集群使用自己设计的简单散列算法CRC16(key)%16384,而非一致性散列算法。Redis的作者认为简单散列算法虽然没有一致性散列算法灵活,但效果已经不错了,且实现很简单,增删节点处理起来也很方便。为了与一致性散列算法区别开来,使用简单散列算法的Redis槽一般称为散列槽。

在Redis集群的实际使用中,SET key value命令会计算散列值,从而把key-value对存储到对应的散列槽和主节点中。槽与节点的关系如图6-24所示,key与数据的关系如图所示。

启动Redis集群后,使用Redis客户端连接服务器192.168.11.15上端口为8001的Redis集群节点。

bash 复制代码
$ redis-cli -c -h 192.168.11.15 -p 8001 
192.168.11.15:8001> 

然后执行cluster nodes命令查看当前Redis集群的节点信息。

bash 复制代码
[root@localhost ~]# redis-cli -c -h 192.168.11.15 -p 8001 
192.168.11.15:8001> cluster nodes 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave  12904463a6c7caa958085e008ad0324213883811 0 1598793006608 2 connected 
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave  1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 0 1598793006000 3 connected 
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 master -  0 1598793005587 2 connected 5461-10922 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master -  0 1598793006000 3 connected 10923-16383 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 myself,slave 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 0 1598793005000 7 connected 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 master -  0 1598793006000 7 connected 0-5460

该命令返回值显示了Redis集群中的每个节点的ID、身份、连接数和槽数等信息。从返回值可以看出,整个Redis集群运行正常,其中包含三个主节点和三个从节点。

  • 8001端口的Redis集群主节点存储0~5460的散列槽。
  • 8002端口的Redis集群主节点存储5461~10922的散列槽。
  • 8003端口的Redis集群主节点存储10923~16383的散列槽。

这三个主节点存储的所有槽组成Redis集群的存储槽位。从节点是主节点的备份,不显示存储槽位。

使用散列槽可以方便地增加或移除节点。当需要增加节点时,只需要把其他节点的某些散列槽挪到新节点就可以了。当需要移除节点时,只需要把待移除节点上的散列槽挪到其他节点就可以了。增加或移除节点的时候不需要先停止所有Redis服务。

一个Redis集群总共有16384个散列槽,一个散列槽中会有很多key-value对。这一结构可以理解成表的分区:使用单机的redis时只有一个表,所有的key都放在这个表里;改用Redis集群以后会自动生成16384个分区表,增加数据时根据简单散列算法来决定key应该存储在哪个分区,每个分区可以存储很多key。

可以使用cluster info命令查看Redis集群信息。

bash 复制代码
192.168.11.15:8005> 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:7 
cluster_my_epoch:7 
cluster_stats_messages_ping_sent:1225 
cluster_stats_messages_pong_sent:1253 
cluster_stats_messages_sent:2478 
cluster_stats_messages_ping_received:1253 
cluster_stats_messages_pong_received:1224 
cluster_stats_messages_fail_received:1 
cluster_stats_messages_received:2478

当我们执行SET age 23命令时,Redis是如何将数据保存到集群中的呢?

bash 复制代码
192.168.11.15:8001> SET age 23 
-> Redirected to slot [741] located at 192.168.11.15:8005 
OK 
192.168.11.15:8005>

输入SET age 23命令后,Redis的执行步骤如下。

(1)接收命令SET age 23。

(2)通过key(age)计算出对应的槽,然后根据槽找到对应的节点。​(age对应的槽为741)

(3)重定向到对应的节点执行命令。

整个Redis集群提供了16384个槽,也就是说集群中各节点分得的槽数总和为16384。Redis集群实现了将16384个槽平均分配给了N个节点,如图所示。

如果有部分槽没有指定到Redis节点,那么这部分槽所对应的keys将不能使用。Redis集群的数据分散度高,键值分布与业务无关,键值无法顺序访问,支持批量操作。

3.5、新增Redis集群节点

把6个Redis节点部署在一台Linux服务器上,采用三主三从的模式启动Redis集群。本小节我们进行Redis集群的水平扩展实验,在原始Redis集群基础上新增两个Redis节点,一个主节点(端口为8007)和一个从节点(端口为8008)​。Redis集群新增节点的架构如图所示。新增Redis节点的顺序是先增加主节点,然后再增加从节点。

1.新增Redis主节点(1)新增Redis节点

新增一个Redis节点,需要在/usr/local/redis-cluster目录下创建相应的文件夹。本例执行以下操作创建8007文件夹。

bash 复制代码
$ cd /usr/local/redis-cluster/ 
$ mkdir 8007 

复制8001文件夹下的redis.conf配置文件到8007文件夹下。

bash 复制代码
cp /usr/local/redis/conf/redis.conf /usr/local/redis-cluster/8007 

修改redis.conf配置文件的配置项。

bash 复制代码
# 开启Redis的守护进程 
daemonize  yes                    
 
# 设置Redis节点的端口号 
port  8007    
 
# 设置数据文件存放位置。必须指定不同的存放位置,否则会丢失数据 
dir  /usr/local/redis-cluster/8007/  
 
# 启动集群模式 
cluster-enabled  yes   
 
# 设置集群节点信息文件,要和节点的端口对应上       
cluster-config-file  nodes-8007.conf   
 
# 设置集群节点的超时时限,单位为毫秒 
cluster-node-timeout  5000          
 
# 修改为Linux服务器的IP 
bind  192.168.11.15                
 
# 关闭保护模式 
protected-mode  no         
 
# 开启AOF持久化。开启AOF持久化后,每次Redis的写操作都会记录一条日志 
appendonly  yes

(2)启动新增的Redis节点

启动端口为8007的Redis节点。

bash 复制代码
[root@localhost ~]# redis-server /usr/local/redis-cluster/8007/redis.conf 
16904:C 30 Aug 2020 21:13:34.953 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 
16904:C 30 Aug 2020 21:13:34.953 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=16904, just started 
16904:C 30 Aug 2020 21:13:34.953 # Configuration loaded

查看Redis节点的进程启动情况,从图可以看出端口为8007的Redis节点已经启动成功。

这时查看Redis集群的节点信息,会发现并没有端口为8007的Redis节点信息。还需要增加Redis主节点。

bash 复制代码
[root@localhost ~]# redis-cli -c -h 192.168.11.15 -p 8001 
192.168.11.15:8001> cluster nodes 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave 12904463a6c7caa958085e008ad0324213883811 0 1598793291000 2 connected 
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 0 1598793291302 3 connected 
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 master - 0 1598793291607 2 connected 5461-10922 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master - 0 1598793291503 3 connected 10923-16383 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 myself,slave 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 0 1598793289000 7 connected 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 master - 0 1598793291000 7 connected 0-5460

(3)增加Redis主节点

Redis集群增加Redis主节点的命令如下。

bash 复制代码
$ redis-cli --cluster add-node 192.168.11.15:8007 192.168.11.15:8001 

redis-cli--cluster命令参数说明如下。

  • 第一个参数add-node表示添加Redis节点。
  • 第二个参数192.168.11.15:8007指定待增加的Redis主节点。
  • 第三个参数192.168.11.15:8001可以是Redis集群中的任何一个Redis节点。

执行命令后,如果响应信息的最后有"​OKNew nodeadded correctly."提示就代表Redis主节点添加成功了。

bash 复制代码
[root@localhost ~]# redis-cli --cluster add-node 192.168.11.15:8007 192.168.11.
15:8001 
>>> Adding node 192.168.11.15:8007 to cluster 192.168.11.15:8001 
>>> Performing Cluster Check (using node 192.168.11.15:8001) 
S: fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001 
  slots: (0 slots) slave 
  replicates 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 
S: 7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005 
  slots: (0 slots) slave 
  replicates 12904463a6c7caa958085e008ad0324213883811 
S: 0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006 
  slots: (0 slots) slave 
  replicates 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 
M: 12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002 
  slots:[5461-10922] (5462 slots) master 
  1 additional replica(s) 
M: 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003 
  slots:[10923-16383] (5461 slots) master 
  1 additional replica(s) 
M: 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004 
  slots:[0-5460] (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. 
>>> Send CLUSTER MEET to node 192.168.11.15:8007 to make it join the cluster. 
[OK] New node added correctly.

使用cluster info命令查看Redis集群信息,从图可以看到Redis节点为7个。

使用cluster nodes命令查看Redis集群的节点信息。可以看到端口为8007的Redis节点状态为master,但是现在没有散列槽分配给这个Redis节点。

bash 复制代码
192.168.11.15:8001> cluster nodes 
484b7c18a54a1690e4fda5361023d7d83d529354 192.168.11.15:8007@18007 master - 0 1598793466000 0 connected 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave 12904463a6c7caa958085e008ad0324213883811 0 1598793466000 2 connected 
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave 1c58e 8b6ae18751ad98858aa9d7ea2c710d1511c 0 1598793466000 3 connected 
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 master - 0 1598793466539 2 connected 5461-10922 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master - 0 1598793466945 3 connected 10923-16383 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 myself,slave 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 0 1598793466000 7 connected 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 master - 0 1598793466000 7 connected 0-5460

新增Redis集群节点成功以后,新增的Redis节点不会有任何数据,因为它还没有分配到任何的散列槽,我们需要为新节点手动分配散列槽。

(4)为Redis主节点分配散列槽

为Redis主节点手动分配散列槽的命令如下。

bash 复制代码
$ redis-cli --cluster reshard 192.168.11.15:8007 

redis-cli--cluster命令参数说明如下。

  • 第一个参数reshard表示为Redis节点手动分配散列槽。
  • 第二个参数192.168.11.15:8007指定待分配的Redis主节点。

分配散列槽有以下两种方式。

  • 方式1:从所有主节点拿出适量的散列槽分配到目标节点,这里的目标节点指新增加的Redis主节点。
  • 方式2:从指定的主节点拿出指定数量的散列槽分配到目标节点。

针对这两种分配散列槽的方式,我们做两个实验。

实验1:从所有的Redis主节点中拿出1000个散列槽分配给主节点192.168.11.15:8007。

bash 复制代码
[root@localhost ~]# redis-cli --cluster reshard 192.168.11.15:8007 
>>> Performing Cluster Check (using node 192.168.11.15:8007) 
M: 484b7c18a54a1690e4fda5361023d7d83d529354 192.168.11.15:8007 
  slots: (0 slots) master 
S: 0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006 
  slots: (0 slots) slave 
  replicates 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 
S: 7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005 
  slots: (0 slots) slave 
  replicates 12904463a6c7caa958085e008ad0324213883811 
M: 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004 
  slots:[0-5460] (5461 slots) master 
  1 additional replica(s) 
S: fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001 
  slots: (0 slots) slave 
  replicates 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 
M: 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003 
  slots:[10923-16383] (5461 slots) master 
  1 additional replica(s) 
M: 12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002 
  slots:[5461-10922] (5462 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. 
How many slots do you want to move (from 1 to 16384)?

命令执行过程中,会询问要分出多少个槽。输入1000,按Enter键继续。

询问分给哪个节点。输入Redis节点192.168.11.15:8007的ID(484b7c18a54a1690e4fda5361023d7d83d529354)​,按Enter键继续。

询问从哪些主节点拿出散列槽分配到新节点。输入all,表示从所有主节点拿出散列槽分配到主节点192.168.11.15:8007,然后按Enter键继续。

bash 复制代码
How many slots do you want to move (from 1 to 16384)? 1000 
What is the receiving node ID? 484b7c18a54a1690e4fda5361023d7d83d529354 
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

然后在响应消息中会有提示"Do you want to proceedwith the proposed reshard plan(yes/no)?​"​,询问是否允许这个分配散列槽的计划。输入yes,然后按Enter键继续。

然后连接Redis集群,查看集群信息。

bash 复制代码
[root@localhost ~]# redis-cli -c -h 192.168.11.15 -p 8001 
192.168.11.15:8001> cluster nodes 
484b7c18a54a1690e4fda5361023d7d83d529354 192.168.11.15:8007@18007 master - 0 1598793719413 8 connected 0-332 5461-5794 10923-11255 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave 12904463a6c7caa958085e008ad0324213883811 0 1598793719000 2 connected 
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 0 1598793718405 3 connected 
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 master - 0 1598793718908 2 connected 5795-10922 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master - 0 1598793718505 3 connected 11256-16383 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 myself,slave 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 0 1598793717000 7 connected 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 master - 0 1598793719514 7 connected 333-5460

从以上消息可以看出Redis节点192.168.11.15:8007已经有散列槽,可以在这个节点进行读写操作了,并且这个Redis节点是主节点。

Redis节点192.168.11.15:8007的散列槽范围是0~332,5461~5794,10923~11255,计算这个Redis节点分配到的槽数总和为(332-0+1)+(5794-5461+1)+(11255-10923+1)=1000,即这个新增的Redis主节点一共分配到了1000个散列槽。

实验2:从Redis主节点192.168.11.15:8002中拿出500个散列槽分配给Redis主节点192.168.11.15:8007。

bash 复制代码
[root@localhost ~]# redis-cli --cluster reshard 192.168.11.15:8007 
>>> Performing Cluster Check (using node 192.168.11.15:8007) 
M: 484b7c18a54a1690e4fda5361023d7d83d529354 192.168.11.15:8007 
  slots:[0-332],[5461-5794],[10923-11255] (1000 slots) master 
S: 0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006 
  slots: (0 slots) slave 
  replicates 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 
S: 7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005 
  slots: (0 slots) slave 
  replicates 12904463a6c7caa958085e008ad0324213883811 
M: 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004 
  slots:[333-5460] (5128 slots) master 
  1 additional replica(s) 
S: fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001 
  slots: (0 slots) slave 
  replicates 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 
M: 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003 
  slots:[11256-16383] (5128 slots) master 
  1 additional replica(s) 
M: 12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002 
  slots:[5795-10922] (5128 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. 

命令执行过程中,会询问要分出多少个槽。输入500,按Enter键继续。

询问分给哪个节点。输入Redis节点192.168.11.15:8007的ID(484b7c18a54a1690e4fda5361023d7d83d529354),按Enter键继续。

询问从哪些主节点拿出散列槽分配到新节点中。输入节点192.168.11.15:8002的ID(12904463a6c7caa958085e008ad0324213883811),表示从指定的节点192.168.11.15:8002拿出散列槽分配到新增节点192.168.11.15:8007。然后输入done,并按Enter键继续。

bash 复制代码
How many slots do you want to move (from 1 to 16384)? 500 
What is the receiving node ID? 484b7c18a54a1690e4fda5361023d7d83d529354 
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: 12904463a6c7caa958085e008ad0324213883811 
Source node #2: done

然后在响应消息中会有提示"Do you want to proceedwith the proposed reshard plan(yes/no)?​"​,询问是否允许这个分配散列槽的计划。输入yes,然后按Enter键继续。

然后连接Redis集群,查看集群信息。

bash 复制代码
192.168.11.15:8001> cluster nodes 
484b7c18a54a1690e4fda5361023d7d83d529354 192.168.11.15:8007@18007 master - 0 1598794023000 8 connected 0-332 5461-6294 10923-11255 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave 12904463a6c7caa958085e008ad0324213883811 0 1598794023747 2 connected 
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 0 1598794023545 3 connected 
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 master - 0 1598794023000 2 connected 6295-10922 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master - 0 1598794024757 3 connected 11256-16383 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 myself,slave 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 0 1598794023000 7 connected 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 master - 0 1598794023043 7 connected 333-5460

Redis节点192.168.11.15:8007的散列槽范围是0~332,5461~6294,10923~11255,计算这个Redis节点分配到的槽数总和为(332-0+1)+(6294-5461+1)+(11255-10923+1)=1500,即这个Redis主节点一共分配到了1500个散列槽。

至此Redis主节点已经添加完毕了,现在的Redis集群结构由三个主节点和三个从节点变成了四个主节点和三个从节点,也就是四主三从模式。

2.新增Redis从节点

(1)新增Redis节点

新增一个Redis节点,需要在/usr/local/redis-cluster目录下创建相应的文件夹。本例执行以下操作创建8008文件夹。

bash 复制代码
$ cd /usr/local/redis-cluster/ 
$ mkdir 8008

复制8001文件夹下的redis.conf配置文件到8008文件夹下。

bash 复制代码
cp /usr/local/redis/conf/redis.conf /usr/local/redis-cluster/8008 

修改redis.conf配置文件的配置项。

bash 复制代码
# 开启Redis的守护进程 
daemonize  yes                    
 
# 设置Redis节点的端口号 
port  8008    
 
# 设置数据文件存放位置。必须指定不同的存放位置,否则会丢失数据 
dir  /usr/local/redis-cluster/8008/  
 
# 启动集群模式 
cluster-enabled  yes   
 
# 设置集群节点信息文件,要和节点的端口对应上       
cluster-config-file  nodes-8008.conf   
 
# 设置集群节点的超时时限,单位为毫秒 
cluster-node-timeout  5000          
 
# 修改为Linux服务器的IP 
bind  192.168.11.15                
 
# 关闭保护模式 
protected-mode  no          
 
# 开启AOF持久化。开始AOF持久化后,每次Redis的写操作都会记录一条日志 
appendonly  yes

(2)启动新增的Redis节点

启动端口为8008的Redis节点。

bash 复制代码
$ redis-server /usr/local/redis-cluster/8008/redis.conf

执行ps-ef|grep redis命令,从图可以看出端口为8008的Redis节点已经启动了。

(3)增加Redis从节点

本实验配置Redis节点192.168.11.15:8008为主节点192.168.11.15:8007的从节点。

添加节点192.168.11.15:8008到Redis集群中去并查看集群信息,如图所示。

bash 复制代码
$ redis-cli --cluster add-node 192.168.11.15:8008 192.168.11.15:8001

再查看Redis集群的节点信息。

bash 复制代码
[root@localhost ~]# redis-cli -c -h 192.168.11.15 -p 8001 
192.168.11.15:8001> cluster nodes 
484b7c18a54a1690e4fda5361023d7d83d529354 192.168.11.15:8007@18007 master - 0 1598794760533 8 connected 0-332 5461-6294 10923-11255 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave 12904463a6c7caa958085e008ad0324213883811 0 1598794761000 2 connected 
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 0 1598794761000 3 connected 
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 master - 0 1598794760634 2 connected 6295-10922 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master - 0 1598794761000 3 connected 11256-16383 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 myself,slave 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 0 1598794761000 7 connected 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 master - 0 1598794761646 7 connected 333-5460 
19bfc02f0753be1c6b14446d463e4b1440f7a850 192.168.11.15:8008@18008 master - 0 1598794761040 0 connected

可以看到端口为8008的节点是一个主节点,没有被分配任何的散列槽,需要执行cluster replicate命令来指定当前节点(从节点)的主节点。

首先,从Redis客户端连接到新增的端口为8008的节点。

bash 复制代码
[root@localhost 7007]# redis-cli -c -h 192.168.11.15 -p 8008

然后,执行cluster replicate命令为当前端口为8008的从节点指定一个主节点,也就是指定当前从节点的主节点ID。本实验将端口为8008的从节点指定为端口为8007的主节点的从节点,端口为8007的主节点的ID是484b7c18a54a1690e4fda5361023d7d83d5293540命令执行结果如图所示。

bash 复制代码
192.168.11.15:8008> CLUSTER REPLICATE 484b7c18a54a1690e4fda5361023d7d83d529354 
OK 

再查看Redis集群的节点信息,会发现Redis节点的槽范围发生了变化。

bash 复制代码
192.168.11.15:8008> cluster nodes 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave 12904463a6c7caa958085e008ad0324213883811 0 1598795008000 2 connected 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 slave 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 0 1598795008277 7 connected 
19bfc02f0753be1c6b14446d463e4b1440f7a850 192.168.11.15:8008@18008 myself,slave 484b7c18a54a1690e4fda5361023d7d83d529354 0 1598795007000 8 connected 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 master - 0 1598795007270 7 connected 333-5460 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master - 0 1598795008579 3 connected 11256-16383 
484b7c18a54a1690e4fda5361023d7d83d529354 192.168.11.15:8007@18007 master - 0 1598795008000 8 connected 0-332 5461-6294 10923-11255 
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 master - 0 1598795008781 2 connected 6295-10922 
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 0 1598795008579 3 connected 

至此Redis集群的水平扩展实验已经实现,搭建了一个四主四从的Redis集群,下一小节进行删除Redis集群节点的实验。

3.6、删除Redis集群节点

本小节进行删除Redis集群节点的实验,删除Redis集群中新增的两个Redis节点,即一个端口为8007的主节点和一个端口号为8008的从节点。

(1)删除从节点

使用redis-cli--cluster del-node命令删除Redis集群中的从节点,完整命令如下。

bash 复制代码
redis-cli --cluster del-node 从节点ip:port 节点id

删除从节点需要指定待删除的从节点的ID地址和端口,以及节点ID。待删除的从节点192.168.11.15:8008的ID是7ef80fd1ef9a403e39d42cfefa56404f9eb6be73。删除从节点的完整命令如图所示。

bash 复制代码
$ redis-cli --cluster del-node 192.168.11.15:8008 19bfc02f0753be1c6b14446d463
e4b1440f7a850

然后连接Redis集群,查看集群信息。

bash 复制代码
[root@localhost ~]# redis-cli -c -h 192.168.11.15 -p 8001 
192.168.11.15:8001> cluster nodes 
484b7c18a54a1690e4fda5361023d7d83d529354 192.168.11.15:8007@18007 master - 0 1598795943590 8 connected 0-332 5461-6294 10923-11255 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave 12904463a6c7caa958085e008ad0324213883811 0 1598795942000 2 connected 
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 0 1598795941579 3 connected
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 master - 0 1598795943000 2 connected 6295-10922 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master - 0 1598795942000 3 connected 11256-16383 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 myself,slave 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 0 1598795942000 7 connected 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 master - 0 1598795942985 7 connected 333-5460

从Redis集群信息可以看出从节点192.168.11.15:8008已经从Redis集群中移除,该节点的Redis服务也已被停止。

(2)删除主节点

删除之前增加的主节点192.168.11.15:8007的步骤相对麻烦一些,因为主节点已分配了散列槽,所以必须先把待删除的主节点的散列槽放入到其他可用的主节点中去,然后再进行移除节点操作,否则会出现数据丢失问题。

删除主节点192.168.11.15:8007,要先将其散列槽分配到其他主节点上。

bash 复制代码
[root@localhost ~]# redis-cli --cluster reshard 192.168.11.15:8007 
>>> Performing Cluster Check (using node 192.168.11.15:8007) 
M: 484b7c18a54a1690e4fda5361023d7d83d529354 192.168.11.15:8007 
  slots:[0-332],[5461-6294],[10923-11255] (1500 slots) master 
S: 0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006 
  slots: (0 slots) slave 
  replicates 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 
S: 7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005 
  slots: (0 slots) slave 
  replicates 12904463a6c7caa958085e008ad0324213883811 
M: 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004 
  slots:[333-5460] (5128 slots) master 
  1 additional replica(s) 
S: fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001 
  slots: (0 slots) slave 
  replicates 3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 
M: 1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003 
  slots:[11256-16383] (5128 slots) master 
  1 additional replica(s) 
M: 12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002 
  slots:[6295-10922] (4628 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. 
How many slots do you want to move (from 1 to 16384)?

命令执行过程中会询问要将多少个散列槽从Redis集群的主节点192.168.11.15:8007移走。因为之前为主节点192.168.11.15:8007分配了1500个散列槽,所以我们在这里输入1500。还要输入接收散列槽的主节点的ID,本例中接收的主节点192.168.11.15:8002的ID是12904463a6c7caa958085e008ad0324213883811。最后输入all,然后按Enter键。

bash 复制代码
How many slots do you want to move (from 1 to 16384)? 1500
What is the receiving node ID? 12904463a6c7caa958085e008ad0324213883811 
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 

然后在响应消息中会有提示"Do you want to proceedwith the proposed reshard plan(yes/no)?​"​,询问是否允许这个分配散列槽的计划。输入yes,然后按Enter键继续。

给主节点192.168.11.15:8007分配散列槽到其他主节点后,就可以删除主节点192.168.11.15:8007了。

bash 复制代码
[root@localhost ~]# redis-cli --cluster del-node 192.168.11.15:8007 484b7c18a54a1690e4fda5361023d7d83d529354 
>>> Removing node 484b7c18a54a1690e4fda5361023d7d83d529354 from cluster 192. 168.11.15:8007 
>>> Sending CLUSTER FORGET messages to the cluster... 
>>> Sending CLUSTER RESET SOFT to the deleted node. 

查看Redis集群信息,可以看到已经没有192.168.11.15:8007这个主节点了。

bash 复制代码
[root@localhost ~]# redis-cli -c -h 192.168.11.15 -p 8001 
192.168.11.15:8001> cluster nodes 
7bc9b1dbd1c4508828dbcb10828e20063c934c9a 192.168.11.15:8005@18005 slave 12904463a6c7caa958085e008ad0324213883811 0 1598798293369 9 connected 
0d8799e882b249fc6bfd655ffcb5a4f89f81efe0 192.168.11.15:8006@18006 slave 12904463a6c7caa958085e008ad0324213883811 0 1598798293573 9 connected 
12904463a6c7caa958085e008ad0324213883811 192.168.11.15:8002@18002 master - 0 1598798293572 9 connected 0-16383 
1c58e8b6ae18751ad98858aa9d7ea2c710d1511c 192.168.11.15:8003@18003 master - 0 1598798294378 3 connected 
fb8600a4f020daeebd85a64369a9aa04b38a7d39 192.168.11.15:8001@18001 myself,slave 12904463a6c7caa958085e008ad0324213883811 0 1598798293000 9 connected 
3d9d3cf8c6fcd7e8adc08095df9b12de7843807e 192.168.11.15:8004@18004 master - 0 1598798295388 7 connected

从Redis集群信息可以看出主节点192.168.11.15:8007已经从Redis集群中移除。

相关推荐
再玩一会儿看代码1 小时前
JUnit 测试框架详解:从实际开发、业务测试到 Java 面试高频问题
java·经验分享·笔记·junit·面试
yxlalm2 小时前
2.java秒杀项目第二课-后端登录功能
java·开发语言
亦暖筑序3 小时前
AgentScope-Java 入门:用 SSE 展示评审任务进度
java·agent·ai编程
记忆停留w3 小时前
Celery+Redis 分布式异步任务队列工程落地业务逻辑
大数据·人工智能·redis·分布式·缓存·架构·wpf
卓怡学长3 小时前
w261springboot基于web学校课程管理系统
java·数据库·spring boot·spring·intellij-idea
shuoshuohaohao3 小时前
《JavaWeb --2》
java
浩瀚地学3 小时前
【面试算法笔记】0105-数组-螺旋矩阵
java·开发语言·笔记·算法·面试
AI人工智能+电脑小能手3 小时前
【大白话说Java面试题 第169题】【07_Redis篇】第5题:如何保证缓存一致性?
java·redis·延迟双删·缓存一致性·双写一致性
SimonKing3 小时前
Spring I18N 底层源码大揭秘:你的 MessageSource 到底是怎么找到配置的?
java·后端·程序员