Linux部署Redis集群

Redis简介

Redis (REmote DIctionary Server) 是一个高性能的 key-value 数据库,完全开源,遵守 BSD 协议。

Redis 与其他 key - value 缓存产品相比有以下三个特点:

  • Redis支持数据持久化,可以将内存中的数据保存在磁盘中,重启时可以再次加载进行使用。
  • Redis不仅仅支持简单的key-value类型数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。

Redis 官网:https://redis.io/

Redis集群简介

Redis Cluster实现在多个节点之间进行数据共享,即使部分节点失效或者无法进行通讯时,Cluster仍然可以继续处理请求。

若每个主节点都有一个从节点支持,在主节点下线或者无法与集群的大多数节点进行通讯的情况下, 从节点提升为主节点,并提供服务,保证Cluster正常运行。

Redis Cluster的节点分片是通过哈希槽(hash slot)实现的,每个键都属于这 16384(0~16383) 个哈希槽的其中一个,每个节点负责处理一部分哈希槽。

Redis 集群部署

redis要求至少3主3从共6个节点才能组成redis集群,每个主节点至少有一个从节点,测试环境可一台物理上启动6个redis节点,但生产环境至少要准备3台物理机。

部署架构图如下:

这里演示使用3台centos7.8服务器,每台起2个服务,共6个节点。

主机名

节点IP

实例1端口

实例2端口

redis01

192.168.93.63

7000

7001

redis02

192.168.93.64

7000

7001

redis03

192.168.93.65

7000

7001

编译安装redis 6.x版本要求gcc版本5.3以上,所有节点安装gcc

复制代码
yum install -y centos-release-scl
yum install -y devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils 
yum install -y systemd-devel

echo "source /opt/rh/devtoolset-9/enable" >> /etc/profile
source /etc/profile
gcc -v

所有节点创建相关目录

复制代码
mkdir -p /opt/redis/{conf,data,log}
mkdir -p /opt/redis/data/{7000,7001}

useradd -s /sbin/nologin redis
chown -R redis: /opt/redis

当前目录结构

复制代码
[root@redis01 ~]# tree /opt/redis/
/opt/redis/
├── conf
├── data
│   ├── 7000
│   └── 7001
└── log

下载redis,下载地址:http://download.redis.io/releases/

复制代码
cd /opt/
wget http://download.redis.io/releases/redis-6.0.9.tar.gz

每个节点编译安装redis

复制代码
tar -zxvf redis-6.0.9.tar.gz
cd  redis-6.0.9

#need systemd-devel
make BUILD_WITH_SYSTEMD=yes USE_SYSTEMD=yes
make install

#查看redis版本
redis-cli --version
redis-server --version

创建redis.conf配置文件,修改以下参数,在第一个节点执行:

复制代码
cp /opt/redis-6.0.9/redis.conf /opt/redis/conf/7000.conf
chown redis: /opt/redis/conf/7000.conf

修改redis配置文件/opt/redis/conf/7000.conf,找到以下参数并手动修改:

复制代码
[root@redis01 ~]# vim /opt/redis/conf/7000.conf
bind 127.0.0.1 192.168.93.63
port 7000
logfile /opt/redis/log/redis_7000.log
dir /opt/redis/data/7000/
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 15000
appendonly yes

配置参数说明:

  • bind 绑定的主机地址
  • port 指定Redis监听端口,默认端口为6379
  • logfile 日志记录方式,默认为标准输出
  • dir 本地数据库存储路径
  • cluster-enabled yes 开启集群功能,否则节点是一个普通的单一redis实例
  • cluster-config-file nodes.conf 集群自动生成的配置文件,保存集群信息
  • cluster-node-timeout 15000 集群中节点能够失联的最大时间
  • appendonly yes 持久化记录服务器执行的所有写操作命令

复制配置文件并修改端口,使用-p参数保留文件权限

复制代码
cp -p /opt/redis/conf/7000.conf /opt/redis/conf/7001.conf
sed -i "s#7000#7001#g" /opt/redis/conf/7001.conf

配置第一个节点对所有节点免密

复制代码
ssh-keygen #默认下一步
ssh-copy-id 192.168.93.64
ssh-copy-id 192.168.93.65

分发配置到另外2个节点

复制代码
#所有节点安装rsync
yum install -y rsync

#保留文件权限属性
rsync -avz /opt/redis/conf/*.conf 192.168.93.64:/opt/redis/conf
rsync -avz /opt/redis/conf/*.conf 192.168.93.65:/opt/redis/conf

替换IP地址

复制代码
#访问redis02替换IP地址
sed -i "s#192.168.93.63#192.168.93.64#g" `grep -rl 192.168.93.63 /opt/redis/conf`

#访问redis03替换IP地址
sed -i "s#192.168.93.63#192.168.93.65#g" `grep -rl 192.168.93.63 /opt/redis/conf`

使用systemd管理reids服务

创建服务启动文件,其中%i为占位符变量,redis@7000.service中@符号后的7000参数会替换该变量:

复制代码
cat > /etc/systemd/system/redis@.service << EOF
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
User=redis
Group=redis
Type=notify
ExecStart=/usr/local/bin/redis-server /opt/redis/conf/%i.conf --daemonize no --supervised systemd
ExecStop=/usr/local/bin/redis-cli -p %i shutdown
LimitNOFILE=10240
TimeoutStartSec=90s
TimeoutStopSec=90s
Restart=always

[Install]
WantedBy=multi-user.target
EOF

分发启动文件到另外2个节点

复制代码
scp /etc/systemd/system/redis@.service 192.168.93.64:/etc/systemd/system/
scp /etc/systemd/system/redis@.service 192.168.93.65:/etc/systemd/system/

所有节点启动redis实例,并设为开机启动

复制代码
systemctl daemon-reload
systemctl enable --now redis@{7000,7001}.service

确认所有节点服务启动成功

复制代码
[root@redis01 ~]# systemctl enable --now redis@{7000,7001}.service
Created symlink from /etc/systemd/system/multi-user.target.wants/redis@7000.service to /etc/systemd/system/redis@.service.
Created symlink from /etc/systemd/system/multi-user.target.wants/redis@7001.service to /etc/systemd/system/redis@.service.
[root@redis01 ~]# 

[root@redis01 ~]# systemctl status redis@{7000,7001}.service
● redis@7000.service - Redis persistent key-value database
   Loaded: loaded (/etc/systemd/system/redis@.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2020-11-08 18:35:33 CST; 8s ago
 Main PID: 24483 (redis-server)
   Status: "Ready to accept connections"
   CGroup: /system.slice/system-redis.slice/redis@7000.service
           └─24483 /usr/local/bin/redis-server 127.0.0.1:7000 [cluster]

Nov 08 18:35:33 redis01 systemd[1]: Starting Redis persistent key-value database...
Nov 08 18:35:33 redis01 systemd[1]: Started Redis persistent key-value database.

● redis@7001.service - Redis persistent key-value database
   Loaded: loaded (/etc/systemd/system/redis@.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2020-11-08 18:35:33 CST; 8s ago
 Main PID: 24484 (redis-server)
   Status: "Ready to accept connections"
   CGroup: /system.slice/system-redis.slice/redis@7001.service
           └─24484 /usr/local/bin/redis-server 127.0.0.1:7001 [cluster]

Nov 08 18:35:33 redis01 systemd[1]: Starting Redis persistent key-value database...
Nov 08 18:35:33 redis01 systemd[1]: Started Redis persistent key-value database.

实例状态维护

复制代码
#查看实例运行状态
systemctl status redis@7000.service
systemctl status redis@7001.service

#启动实例
systemctl start redis@7000.service
systemctl start redis@7001.service

#停止实例
systemctl stop redis@7000.service
systemctl stop redis@7001.service

#重启实例
systemctl restart redis@7000.service
systemctl restart redis@7001.service

也可以通过redis命令启停实例,需要在配置文件中启用daemonize yes后台模式运行:

复制代码
#启动单个redis实例
redis-server /opt/redis/conf/7000.conf

#关闭单个redis实例
redis-cli -h 192.168.93.63 -p 7000 shutdown

实例全部启动后,任意节点创建redis集群

复制代码
redis-cli --cluster create 

--cluster-replicas 1

192.168.93.63:7000

192.168.93.63:7001

192.168.93.64:7000

192.168.93.64:7001

192.168.93.65:7000

192.168.93.65:7001

创建完成后看到这样的消息:All 16384 slots covered。这意味着至少有一个主实例为16384个可用slot提供服务。

查看集群节点状态,创建了3个master节点及3个slave节点,每个节点7000端口被自动指定为master节点:

复制代码
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7000 cluster nodes
e9aa81c8d241f12b8495d0cd0ca5d468fdc963ad 192.168.93.64:7001@17001 slave 4f3f37a897221aff7211d26438f0277072622f72 0 1604831830898 1 connected
4f3f37a897221aff7211d26438f0277072622f72 192.168.93.63:7000@17000 myself,master - 0 1604831826000 1 connected 0-5460
dc061b8f217edf24fe1e64d9bace2023a2ef0463 192.168.93.65:7001@17001 slave 0b5d3c032c4f4605b65d75b5c39bcfca8ac4e188 0 1604831828859 3 connected
b84d17598bd1af1229430d85bbff143f9afa6761 127.0.0.1:7001@17001 slave 5b3e17e24ee7faab6d5da26cfaccb389c91c4ce5 0 1604831833961 5 connected
5b3e17e24ee7faab6d5da26cfaccb389c91c4ce5 192.168.93.65:7000@17000 master - 0 1604831831923 5 connected 10923-16383
0b5d3c032c4f4605b65d75b5c39bcfca8ac4e188 192.168.93.64:7000@17000 master - 0 1604831832944 3 connected 5461-10922

查看集群信息,cluster_state为ok ,cluster_size为3,cluster_known_nodes为6。

复制代码
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7000 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:45
cluster_stats_messages_pong_sent:47
cluster_stats_messages_sent:92
cluster_stats_messages_ping_received:42
cluster_stats_messages_pong_received:45
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:92

查看redis主从状态信息,当前192.168.93.63:7000端口实例绑定的slave实例为192.168.93.64:7001

复制代码
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7000 info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.93.64,port=7001,state=online,offset=70,lag=1
master_replid:e0a3de62f2acca98c993353e52cdcbef0b83312f
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:70

验证数据写入,使用 -c 参数连接redis集群任意节点,主备节点都支持写入和读取数据

复制代码
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7000 set key1 value1
OK
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7000 get key1
"value1"

[root@redis01 ~]# redis-cli -c -h 192.168.93.64 -p 7001 set key2 value2
OK
[root@redis01 ~]# redis-cli -c -h 192.168.93.64 -p 7001 get key2
"value2"

而不使用-c参数时master节点可正常读写,但slave节点无法写入和读取数据

复制代码
[root@redis01 ~]# redis-cli -h 192.168.93.63 -p 7000 set key3 value3
OK

[root@redis01 ~]# redis-cli -h 192.168.93.64 -p 7001 set key4 value4
(error) MOVED 13120 192.168.93.65:7000

[root@redis01 ~]# redis-cli -h 192.168.93.64 -p 7001 get key3
(error) MOVED 935 192.168.93.63:7000

配置slave节点为readonly模式,可在slave节点执行读操作

复制代码
[root@redis01 ~]# redis-cli -h 192.168.93.64 -p 7001
192.168.93.64:7001> readonly
OK
192.168.93.64:7001> get key3
"value3"
192.168.93.64:7001> 

查看所有master节点,3个master节点,每个master连接一个slave:

复制代码
[root@redis01 ~]# redis-cli --cluster info 192.168.93.63:7000
192.168.93.63:7000 (4f3f37a8...) -> 2 keys | 5461 slots | 1 slaves.
192.168.93.65:7000 (5b3e17e2...) -> 0 keys | 5461 slots | 1 slaves.
192.168.93.64:7000 (0b5d3c03...) -> 1 keys | 5462 slots | 1 slaves.
[OK] 3 keys in 3 masters.
0.00 keys per slot on average.

当前的Redis数据目录结构,其中/opt//redis/conf/data/port下自动生成了多个文件:

复制代码
[root@redis01 ~]# tree /opt/redis
/opt/redis
├── conf
│   ├── 7000.conf
│   └── 7001.conf
├── data
│   ├── 7000
│   │   ├── appendonly.aof
│   │   ├── dump.rdb
│   │   └── nodes-7000.conf
│   └── 7001
│       ├── appendonly.aof
│       ├── dump.rdb
│       └── nodes-7001.conf
└── log
    ├── redis_7000.log
    └── redis_7001.log

配置文件说明:

  • appendonly.aof 以AOF方式持久化数据,以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来
  • dump.rdb 内存快照数据,服务器宕机重启后redis会自动加载dump.rdb恢复上次SNAPSHOT状态
  • nodes.conf 集群节点信息文件,Redis集群实例启动时自动生成

测试故障转移

停止192.168.93.63:7000 master节点,依然可以连接其他节点get数据:

复制代码
[root@redis01 ~]# systemctl stop redis@7000.service

从7001端口查看集群状态,提示7000端口无法连接,但依然是3个master节点,192.168.93.64:7001 代替了7000成为master节点,但该节点具有0个slaves。

复制代码
[root@redis01 ~]# redis-cli --cluster info 192.168.93.63:7001
Could not connect to Redis at 192.168.93.63:7000: Connection refused
192.168.93.64:7001 (e9aa81c8...) -> 2 keys | 5461 slots | 0 slaves.
192.168.93.64:7000 (0b5d3c03...) -> 1 keys | 5462 slots | 1 slaves.
192.168.93.65:7000 (5b3e17e2...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 3 keys in 3 masters.
0.00 keys per slot on average.

查看集群节点状态,原192.168.93.63:7000节点处于fail状态:

复制代码
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7001 cluster nodes
dc061b8f217edf24fe1e64d9bace2023a2ef0463 192.168.93.65:7001@17001 slave 0b5d3c032c4f4605b65d75b5c39bcfca8ac4e188 0 1604832178068 3 connected
4f3f37a897221aff7211d26438f0277072622f72 192.168.93.63:7000@17000 master,fail - 1604832118835 1604832112709 1 disconnected
e9aa81c8d241f12b8495d0cd0ca5d468fdc963ad 192.168.93.64:7001@17001 master - 0 1604832180109 7 connected 0-5460
0b5d3c032c4f4605b65d75b5c39bcfca8ac4e188 192.168.93.64:7000@17000 master - 0 1604832179089 3 connected 5461-10922
5b3e17e24ee7faab6d5da26cfaccb389c91c4ce5 192.168.93.65:7000@17000 master - 0 1604832176025 5 connected 10923-16383
b84d17598bd1af1229430d85bbff143f9afa6761 192.168.93.63:7001@17001 myself,slave 5b3e17e24ee7faab6d5da26cfaccb389c91c4ce5 0 1604832107000 5 connected

重新启动7000节点,该节点成为slave

复制代码
[root@redis01 ~]# systemctl start redis@7000.service
[root@redis01 ~]# 
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7001 cluster nodes
dc061b8f217edf24fe1e64d9bace2023a2ef0463 192.168.93.65:7001@17001 slave 0b5d3c032c4f4605b65d75b5c39bcfca8ac4e188 0 1604832244468 3 connected
4f3f37a897221aff7211d26438f0277072622f72 127.0.0.1:7000@17000 slave e9aa81c8d241f12b8495d0cd0ca5d468fdc963ad 0 1604832240377 7 connected
e9aa81c8d241f12b8495d0cd0ca5d468fdc963ad 192.168.93.64:7001@17001 master - 0 1604832242422 7 connected 0-5460
0b5d3c032c4f4605b65d75b5c39bcfca8ac4e188 192.168.93.64:7000@17000 master - 0 1604832241400 3 connected 5461-10922
5b3e17e24ee7faab6d5da26cfaccb389c91c4ce5 192.168.93.65:7000@17000 master - 0 1604832243445 5 connected 10923-16383
b84d17598bd1af1229430d85bbff143f9afa6761 192.168.93.63:7001@17001 myself,slave 5b3e17e24ee7faab6d5da26cfaccb389c91c4ce5 0 1604832238000 5 connected

从上述实验得知,如果其中任一个master节点kill掉,都会由该master下的其他从节点替换成为新master,原master启动后会变成从节点;重新启动的从节点会同步master数据。

单个节点中中单个实例故障示意图:

单个服务器节点故障示意图:

手动故障切换

参考:http://www.redis.cn/commands/cluster-failover.html

cluster failover命令能够实现master和slave接角色互换,该命令只能在群集slave节点执行,让slave节点进行一次人工故障切换。

人工故障切换是预期的操作,而非发生了真正的故障,目的是以一种安全的方式(数据无丢失)将当前master节点和其中一个slave节点(执行cluster-failover的节点)交换角色。

连接到7000的slave节点,执行角色互换,可以看到7000再次成为master节点:

复制代码
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7000 cluster failover
OK
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7000 cluster nodes
e9aa81c8d241f12b8495d0cd0ca5d468fdc963ad 192.168.93.64:7001@17001 slave 4f3f37a897221aff7211d26438f0277072622f72 0 1604832314440 8 connected
0b5d3c032c4f4605b65d75b5c39bcfca8ac4e188 192.168.93.64:7000@17000 master - 0 1604832311378 3 connected 5461-10922
dc061b8f217edf24fe1e64d9bace2023a2ef0463 192.168.93.65:7001@17001 slave 0b5d3c032c4f4605b65d75b5c39bcfca8ac4e188 0 1604832315461 3 connected
5b3e17e24ee7faab6d5da26cfaccb389c91c4ce5 192.168.93.65:7000@17000 master - 0 1604832311000 5 connected 10923-16383
b84d17598bd1af1229430d85bbff143f9afa6761 127.0.0.1:7001@17001 slave 5b3e17e24ee7faab6d5da26cfaccb389c91c4ce5 0 1604832313416 5 connected
4f3f37a897221aff7211d26438f0277072622f72 192.168.93.63:7000@17000 myself,master - 0 1604832307000 8 connected 0-5460

另外该命令有如下两个选项:FORCE和TAKEOVER:

1、FORCE 选项:master节点down的情况下的人工故障转移

Slave节点不和master协商(master也许已不可达)。当master已不可用,而我们想要做人工故障转移时,该选项很有用。

但是,即使使用FORCE选项,我们依然需要群集中大多数master节点有效,以便对这次切换进行验证,同时为将成为新master的salve节点生成新的配置epoch。

2、TAKEOVER 选项: 忽略群集一致验证的的人工故障切换

有时会有这种情况,群集中master节点不够,我们想在未和群集中其余master节点验证的情况下进行故障切换。

实际用途举例:群集中主节点和从节点在不同的数据中心,当所有主节点down掉或被网络分区隔离,需要用该参数将slave节点 批量切换为master节点。

选项 TAKEOVER 实现了FORCE的所有功能,同时为了能够进行故障切换放弃群集验证。

添加主节点

redis03服务器中添加一个主节点192.168.93.65:7003。

复制代码
#创建配置文件
[root@redis03 ~]# cp -p /opt/redis/conf/7000.conf /opt/redis/conf/7003.conf
[root@redis03 ~]# sed -i "s#7000#7003#g" /opt/redis/conf/7003.conf

#创建数据目录
mkdir /opt/redis/data/7003
chown redis: /opt/redis/data/7003

#启动实例
systemctl enable --now redis@7003.service
systemctl status redis@7003.service

新主节点加入集群,前面的ip和端口号为新添加的节点,后面的为集群中任意一个节点。

复制代码
redis-cli --cluster add-node 

192.168.93.65:7003

192.168.93.63:7000

查看7003节点已加入到集群中成为master。

复制代码
[root@redis03 ~]# redis-cli --cluster info 192.168.93.63:7000
192.168.93.63:7000 (4f3f37a8...) -> 2 keys | 5461 slots | 1 slaves.
192.168.93.64:7000 (0b5d3c03...) -> 1 keys | 5462 slots | 2 slaves.
192.168.93.65:7000 (5b3e17e2...) -> 0 keys | 5461 slots | 0 slaves.
192.168.93.65:7003 (caf578ee...) -> 0 keys | 0 slots | 0 slaves.
[OK] 3 keys in 4 masters.
0.00 keys per slot on average.

新的master节点现在已经加入集群,但新节点没有包含任何数据,该节点没有分配哈希槽,为0 slots ,即不能进行数据的存取。需要我们手动对集群进行重新分片迁移。

可以使用rebalance命令重新将哈希槽均衡分布到各个节点:

复制代码
[root@redis01 ~]# redis-cli --cluster rebalance 192.168.93.63:7000 --cluster-use-empty-masters

再次查看哈希槽分配情况,新的master已经分配了4096 slots

复制代码
[root@redis01 ~]# redis-cli --cluster info 192.168.93.63:7000
192.168.93.63:7000 (4f3f37a8...) -> 1 keys | 4096 slots | 1 slaves.
192.168.93.64:7000 (0b5d3c03...) -> 1 keys | 4096 slots | 1 slaves.
192.168.93.65:7000 (5b3e17e2...) -> 0 keys | 4096 slots | 1 slaves.
192.168.93.65:7003 (caf578ee...) -> 1 keys | 4096 slots | 0 slaves.
[OK] 3 keys in 4 masters.
0.00 keys per slot on average.

或者执行reshard命令从指定节点迁移指定数量哈希槽到目标节点,例如从192.168.93.63:7000节点分配1000哈希槽到192.168.93.65:7003节点.

首先需要使用cluster nodes命令获取节点ID,然后执行以下操作(redis-cli --cluster help查看更多命令帮助。)

复制代码
redis-cli --cluster reshard 192.168.93.63:7000 

--cluster-from 4f3f37a897221aff7211d26438f0277072622f72

--cluster-to caf578ee5dff2b8129e81f7b16cf6ee7591baf0f

--cluster-slots 1000

--cluster-yes

再次查看哈希槽分布情况:

复制代码
[root@redis01 ~]# redis-cli --cluster info 192.168.93.63:7000
192.168.93.63:7000 (4f3f37a8...) -> 1 keys | 3096 slots | 1 slaves.
192.168.93.64:7000 (0b5d3c03...) -> 2 keys | 4096 slots | 1 slaves.
192.168.93.65:7000 (5b3e17e2...) -> 0 keys | 4096 slots | 1 slaves.
192.168.93.65:7003 (caf578ee...) -> 0 keys | 5096 slots | 0 slaves.
[OK] 3 keys in 4 masters.
0.00 keys per slot on average.

添加从节点

redis03新添加的master节点7003还没有分配slave节点,在redis02服务器中为其添加一个从节点7004。

同样添加配置文件和启动文件

复制代码
#创建配置文件
[root@redis02 ~]# cp -p /opt/redis/conf/7000.conf /opt/redis/conf/7004.conf
[root@redis02 ~]# sed -i "s#7000#7004#g" /opt/redis/conf/7004.conf

#创建数据目录
mkdir /opt/redis/data/7004
chown redis: /opt/redis/data/7004

#启动实例
systemctl enable --now redis@7004.service
systemctl status redis@7004.service

首先获取7003 master节点nodeid

复制代码
redis-cli -c -h 192.168.93.63 -p 7000 cluster nodes

添加7004从节点到集群,这里选取7003作为7004的master节点,前面ip和端口号是新添加的节点,后面ip和端口号是选取的集群任意节点,cluster-master-id参数为master 7003节点ID:

复制代码
redis-cli --cluster add-node 

192.168.93.64:7004

192.168.93.63:7000

--cluster-slave

--cluster-master-id caf578ee5dff2b8129e81f7b16cf6ee7591baf0f

查看添加的从节点,7003成功绑定到slave7004:

复制代码
[root@redis02 opt]# redis-cli -c -h 192.168.93.63 -p 7000 cluster nodes |grep caf578ee5dff2b8129e81f7b16cf6ee7591baf0f
caf578ee5dff2b8129e81f7b16cf6ee7591baf0f 192.168.93.65:7003@17003 master - 0 1604833502865 11 connected 1000-2364 5461-7826 10923-12287
65f4c058d1c95081ca8616f2553d7190082c8503 192.168.93.64:7004@17004 slave caf578ee5dff2b8129e81f7b16cf6ee7591baf0f 0 1604833504295 11 connected

当然也可以直接添加一个slave节点到集群,不指定该slave节点连接的master节点。在这种情况下,redis-cli会将新节点添加到副本较少的主节点中。

复制代码
redis-cli --cluster add-node 

192.168.93.65:7004

192.168.93.63:7000

--cluster-slave

或者将一个现有的slave节点分配到指定master节点,例如此时7004节点为slave节点,关联到7003master节点,现在将其分配给7000 master节点,必须连接到对应7004节点执行cluster replicate命令:

复制代码
redis-cli -c -h 192.168.93.64 -p 7004 

cluster replicate 4f3f37a897221aff7211d26438f0277072622f72

复制代码
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7000 cluster nodes | grep 4f3f37a897221aff7211d26438f0277072622f72
e9aa81c8d241f12b8495d0cd0ca5d468fdc963ad 192.168.93.64:7001@17001 slave 4f3f37a897221aff7211d26438f0277072622f72 0 1604834083584 8 connected
65f4c058d1c95081ca8616f2553d7190082c8503 192.168.93.64:7004@17004 slave 4f3f37a897221aff7211d26438f0277072622f72 0 1604834084198 8 connected
4f3f37a897221aff7211d26438f0277072622f72 192.168.93.63:7000@17000 myself,master - 0 1604834068000 8 connected 2365-5460

此时连接到集群可以看到7000连接了2个slave,7003slave变为0

复制代码
[root@redis01 ~]#  redis-cli --cluster info 192.168.93.63:7000
192.168.93.63:7000 (4f3f37a8...) -> 1 keys | 3096 slots | 2 slaves.
192.168.93.64:7000 (0b5d3c03...) -> 2 keys | 4096 slots | 1 slaves.
192.168.93.65:7000 (5b3e17e2...) -> 0 keys | 4096 slots | 1 slaves.
192.168.93.65:7003 (caf578ee...) -> 0 keys | 5096 slots | 0 slaves.
[OK] 3 keys in 4 masters.
0.00 keys per slot on average.

[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7000 info replication 
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.93.64,port=7001,state=online,offset=3121,lag=0
slave1:ip=192.168.93.64,port=7004,state=online,offset=3121,lag=0
master_replid:eea34382e417f670906a39d7bcf6eb6995cde2c7
master_replid2:6c0acfb2bd21e03704de15854282ec3235af41a8
master_repl_offset:3135
second_repl_offset:598
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:486
repl_backlog_histlen:2650

删除主从节点

删除从节点

从集群中删除从节点7004,首先指定任意其他节点ip和端口,以及要删除的7004节点id

复制代码
[root@redis01 ~]# redis-cli --cluster del-node 192.168.93.63:7001 65f4c058d1c95081ca8616f2553d7190082c8503
>>> Removing node 65f4c058d1c95081ca8616f2553d7190082c8503 from cluster 192.168.93.63:7001
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.

删除后7004节点从集群退出成为独立节点

复制代码
[root@redis01 ~]# redis-cli -c -h 192.168.93.64 -p 7004 cluster nodes
65f4c058d1c95081ca8616f2553d7190082c8503 192.168.93.64:7004@17004 myself,master - 0 1604863810000 0 connected

删除主节点

注意如果是从节点可直接删除,如果是master节点,并且主节点有从节点,需要将从节点转移到其他主节点。最后如果主节点有slot,先将主节点里的slot分配到其他可用节点中,然后再删除节点才行,否则会有数据丢失。

以删除7003 master节点为例,7003有0个slave节点,5096 个slots,这里将slots移动到192.168.93.63:7000。

复制代码
[root@redis01 ~]# redis-cli --cluster info 192.168.93.63:7000
192.168.93.63:7000 (4f3f37a8...) -> 1 keys | 3096 slots | 1 slaves.
192.168.93.64:7000 (0b5d3c03...) -> 2 keys | 4096 slots | 1 slaves.
192.168.93.65:7000 (5b3e17e2...) -> 0 keys | 4096 slots | 1 slaves.
192.168.93.65:7003 (caf578ee...) -> 0 keys | 5096 slots | 0 slaves.
[OK] 3 keys in 4 masters.
0.00 keys per slot on average.

查看节点ID

复制代码
[root@redis01 ~]# redis-cli -c -h 192.168.93.63 -p 7000 cluster nodes
e9aa81c8d241f12b8495d0cd0ca5d468fdc963ad 192.168.93.64:7001@17001 slave 4f3f37a897221aff7211d26438f0277072622f72 0 1604835174094 8 connected
0b5d3c032c4f4605b65d75b5c39bcfca8ac4e188 192.168.93.64:7000@17000 master - 0 1604835176136 10 connected 0-999 7827-10922
dc061b8f217edf24fe1e64d9bace2023a2ef0463 192.168.93.65:7001@17001 slave 0b5d3c032c4f4605b65d75b5c39bcfca8ac4e188 0 1604835171000 10 connected
5b3e17e24ee7faab6d5da26cfaccb389c91c4ce5 192.168.93.65:7000@17000 master - 0 1604835175118 5 connected 12288-16383
caf578ee5dff2b8129e81f7b16cf6ee7591baf0f 192.168.93.65:7003@17003 master - 0 1604835172052 11 connected 1000-2364 5461-7826 10923-12287
b84d17598bd1af1229430d85bbff143f9afa6761 127.0.0.1:7001@17001 slave 5b3e17e24ee7faab6d5da26cfaccb389c91c4ce5 0 1604835173069 5 connected
4f3f37a897221aff7211d26438f0277072622f72 192.168.93.63:7000@17000 myself,master - 0 1604835172000 8 connected 2365-5460

迁移192.168.93.65:7003所有哈希槽到192.168.93.63:7000

复制代码
redis-cli --cluster reshard 192.168.93.63:7000 

--cluster-from caf578ee5dff2b8129e81f7b16cf6ee7591baf0f

--cluster-to 4f3f37a897221aff7211d26438f0277072622f72

--cluster-slots 5096

--cluster-yes

确认7003 slots已经被完全迁移

复制代码
[root@redis01 ~]# redis-cli --cluster info 192.168.93.63:7000
192.168.93.63:7000 (4f3f37a8...) -> 1 keys | 8192 slots | 1 slaves.
192.168.93.64:7000 (0b5d3c03...) -> 2 keys | 4096 slots | 1 slaves.
192.168.93.65:7000 (5b3e17e2...) -> 0 keys | 4096 slots | 1 slaves.
192.168.93.65:7003 (caf578ee...) -> 0 keys | 0 slots | 0 slaves.
[OK] 3 keys in 4 masters.
0.00 keys per slot on average.

然后删除7003主节点,首先指定其他任意节点ip和端口,以及被删除的7003节点id

复制代码
redis-cli --cluster del-node 192.168.93.63:7000 caf578ee5dff2b8129e81f7b16cf6ee7591baf0f 

7003节点已经从集群退出成为独立节点:

复制代码
[root@redis01 ~]# redis-cli --cluster info 192.168.93.63:7000
192.168.93.63:7000 (4f3f37a8...) -> 1 keys | 8192 slots | 1 slaves.
192.168.93.64:7000 (0b5d3c03...) -> 2 keys | 4096 slots | 1 slaves.
192.168.93.65:7000 (5b3e17e2...) -> 0 keys | 4096 slots | 1 slaves.
[OK] 3 keys in 3 masters.
0.00 keys per slot on average.

清理redis集群

参考:http://www.redis.cn/commands/cluster-reset.html

可以使用cluster reset命令清理集群:

复制代码
[root@localhost ~]#  redis-cli -c -h 192.168.93.63 -p 7000 cluster reset

[root@localhost ~]#  redis-cli -c -h 192.168.93.63 -p 7000 cluster nodes
2de3d18c66ff9c89229197f3d669c789ff60922d 192.168.93.63:7000@17000 myself,master - 0 1604833203000 11 connected

停止所有实例

复制代码
systemctl stop redis@7000.service
systemctl stop redis@7001.service

清理所有节点集群配置信息

复制代码
rm -rf /opt/redis/data/{7000,7001}/data/*

重启所有实例

复制代码
systemctl start redis@7000.service
systemctl start redis@7001.service

最后可以重新创建集群

复制代码
redis-cli --cluster create xxx

参考:
https://redis.io/topics/cluster-tutorial
http://www.redis.cn/topics/cluster-tutorial.html
https://medium.com/opstree-technology/redis-cluster-architecture-replication-sharding-and-failover-86871e783ac0

相关推荐
EMTime16 小时前
Docker运行OpenWRT
运维·docker·容器
lolo大魔王16 小时前
Linux 文件系统超全面详解(原理、结构、挂载、分区、inode、日志、管理命令)
linux·运维·服务器
磊 子18 小时前
详细讲解一下epoll
linux·io·epoll·io多路复用
printfLILEI18 小时前
php中的类与对象以及反序列化
linux·开发语言·php
zyl8372119 小时前
Docker 使用手册
运维·docker·容器
古月方枘Fry19 小时前
MGRE实验
运维·服务器
叠叠乐19 小时前
redmi k90 pro max 强解BL,刷海外rom, 并刷入sukisu ultra
linux
stolentime19 小时前
FreeDomain 本地开发环境快速搭建指南
运维·服务器·网络
xiaoye-duck20 小时前
《Linux系统编程》Linux 进程间通信之管道基础解析:从匿名管道原理到基于管道的进程池实现
linux