redis cluster(去中心化)
集群介绍
Redis3.0加入了Redis的集群模式,通过数据的分布式存储实现去中心化的思想。redis通过对数据进行分片,将不同的数据存储在不同的master节点上面,从而解决了海量数据的存储问题。Redis也内置了高可用机制,支持N个master节点,每个master节点都可以挂载多个slave节点,当master节点挂掉时,集群会提升它的某个slave节点作为新的master节点。
redis集群没有中心节点的说法,对于客户端来说,整个集群可以看成一个整体,可以连接任意一个节点进行操作,就像操作单一Redis实例一样,不需要任何代理中间件,当客户端操作的key没有分配到该node上时,Redis会返回转向指令,指向正确的node。
使用集群场景
(1)写并发:Redis单实例读写分离可以解决读操作的负载均衡,但对于写操作,仍然是全部落在了master节点上面,在海量数据高并发场景,一个节点写数据容易出现瓶颈,造成master节点的压力上升。
(2)海量数据的存储压力: 单实例Redis本质上只有一台Master作为存储,如果面对海量数据的存储,一台Redis服务器就应付不过来了,而且数据量太大意味着持久化成本高,严重时可能会阻塞服务器,造成服务请求成功率下降,降低服务的稳定性。
针对以上的问题,Redis集群提供了较为完善的方案,解决了存储能力受到单机限制,写操作无法负载均衡的问题。
配置集群
主机说明 | 主机IP | 端口 |
---|---|---|
master1 | 192.168.70.20 | 6379 |
slave1 | 192.168.70.20 | 6380 |
master2 | 192.168.70.21 | 6379 |
slave2 | 192.168.70.21 | 6380 |
master3 | 192.168.70.22 | 6379 |
slave3 | 192.168.70.22 | 6380 |
修改redis的配置文件
第一步:
#修改/etc/redis/redis.conf
[root@master1 ~]# hostnamectl set-hostname master1
#其中6379为主的端口号
port 6379
pidfile /var/run/redis_6379.pid
dir /var/lib/redis
dbfilename dump_6379.rdb
bind 0.0.0.0
daemonize yes
protected-mode no
logfile /var/log/redis/redis_6379.log
#此三行配置在注释中
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 10000
#启动第一个redis
[root@master ~]# systemctl restart redis
[root@master ~]# ss -lntup | grep redis
tcp LISTEN 0 511 0.0.0.0:6379 0.0.0.0:* users:(("redis-server",pid=3461,fd=6))
tcp LISTEN 0 511 0.0.0.0:16379 0.0.0.0:* users:(("redis-server",pid=3461,fd=8))
在该主机上启动另外一个6380端口的实例
#复制配置文件,并将原配置文件的6379用sed改为6380
[root@master ~]# cp /etc/redis/redis.conf /etc/redis/redis-6380.conf
[root@master ~]# sed -i 's/6379/6380/' /etc/redis/redis-6380.conf
[root@master ~]# grep 6380 /etc/redis/redis-6380.conf
# Accept connections on the specified port, default is 6380 (IANA #815344).
port 6380
# tls-port 6380
pidfile /var/run/redis_6380.pid
logfile /var/log/redis/redis_6380.log
dbfilename dump_6380.rdb
cluster-config-file nodes-6380.conf
# cluster-announce-tls-port 6380
# cluster-announce-bus-port 6380
#启动第二个redis实例
[root@master ~]# redis-server /etc/redis/redis-6380.conf
#查看是否有两个redis实例
[root@master ~]# ss -lntup | grep redis
tcp LISTEN 0 511 0.0.0.0:6379 0.0.0.0:* users:(("redis-server",pid=3461,fd=6))
tcp LISTEN 0 511 0.0.0.0:6380 0.0.0.0:* users:(("redis-server",pid=3503,fd=6))
tcp LISTEN 0 511 0.0.0.0:16379 0.0.0.0:* users:(("redis-server",pid=3461,fd=8))
tcp LISTEN 0 511 0.0.0.0:16380 0.0.0.0:* users:(("redis-server",pid=3503,fd=8))
将以上两个配置文件复制到另外两外两台主机依次启动
[root@master ~]# scp /etc/redis/redis.conf /etc/redis/redis-6380.conf root@192.168.70.21:/etc/redis
[root@master ~]# scp /etc/redis/redis.conf /etc/redis/redis-6380.conf root@192.168.70.22:/etc/redis
master2
master3
第二步:创建集群
[root@master2 ~]# redis-cli --cluster create --cluster-replicas 1 192.168.70.20:6379 192.168.70.21:6379 192.168.70.22:6379 192.168.70.20:6380 192.168.70.21:6380 192.168.70.22:6380
查看集群状态
[root@master2 ~]# redis-cli cluster nodes
#状态中给出了分配的主和从 以及对应的id
第三步:测试
[root@master2 ~]# redis-cli -c
127.0.0.1:6379> set cluster 3
-> Redirected to slot [14041] located at 192.168.70.22:6379
OK
192.168.70.22:6379> get cluster
"3"
192.168.70.22:6379>
故障转移
#模拟master2宕机
[root@master2 ~]# redis-cli -c
127.0.0.1:6379> shutdown
not connected> exit
[root@master2 ~]# redis-cli -c -p 6380 #因为6379宕机了,指定6380登录
127.0.0.1:6380> cluster nodes
#可以看到宕机掉的主被从所替换
#再次启动
[root@master2 ~]# systemctl start redis
[root@master2 ~]# redis-cli -c
127.0.0.1:6379> cluster nodes
#可以看到master2变成了从
集群扩容
向现有集群中添加两个节点,这两个节点做一主一从。主节点的端口号为 6381,从节点的端口号为 6382。
[root@master ~]# cp /etc/redis/redis.conf /etc/redis/redis-6381.conf
[root@master ~]# cp /etc/redis/redis.conf /etc/redis/redis-6382.conf
[root@master ~]# sed -i 's/6379/6381/ ' /etc/redis/redis-6381.conf
[root@master ~]# sed -i 's/6379/6382/ ' /etc/redis/redis-6382.conf
[root@master ~]# redis-server /etc/redis/redis-6381.conf
[root@master ~]# redis-server /etc/redis/redis-6382.conf
[root@master ~]# ss -lntup | grep redis
tcp LISTEN 0 511 0.0.0.0:6379 0.0.0.0:* users:(("redis-server",pid=3461,fd=6))
tcp LISTEN 0 511 0.0.0.0:6382 0.0.0.0:* users:(("redis-server",pid=3529,fd=6))
tcp LISTEN 0 511 0.0.0.0:6380 0.0.0.0:* users:(("redis-server",pid=3503,fd=6))
tcp LISTEN 0 511 0.0.0.0:6381 0.0.0.0:* users:(("redis-server",pid=3523,fd=6))
tcp LISTEN 0 511 0.0.0.0:16379 0.0.0.0:* users:(("redis-server",pid=3461,fd=8))
tcp LISTEN 0 511 0.0.0.0:16382 0.0.0.0:* users:(("redis-server",pid=3529,fd=8))
tcp LISTEN 0 511 0.0.0.0:16380 0.0.0.0:* users:(("redis-server",pid=3503,fd=8))
tcp LISTEN 0 511 0.0.0.0:16381 0.0.0.0:* users:(("redis-server",pid=3523,fd=8))
添加主节点
[root@master ~]# redis-cli --cluster add-node 192.168.70.20:6381 192.168.70.20:6379
[root@master ~]# redis-cli
127.0.0.1:6379> cluster nodes
28c8ded8f4aa828c5a8566484aae881d62edea80 192.168.70.22:6379@16379 master - 0 1757502551000 3 connected 10923-16383
1cd96a083b2eebc5cea5d0321e1a9b6ac920b57f 192.168.70.20:6379@16379 myself,master - 0 1757502550000 1 connected 0-5460
3efb6c4070e9faa0b36fa1ccbf3dde452953e7d4 192.168.70.21:6380@16380 slave 1cd96a083b2eebc5cea5d0321e1a9b6ac920b57f 0 1757502552032 1 connected
4fb00272746c7fe092d161b6e2517098c457c314 192.168.70.22:6380@16380 master - 0 1757502552032 7 connected 5461-10922
51d4c8f057354490773ab320fd2c9a5125a96c53 192.168.70.21:6379@16379 slave 4fb00272746c7fe092d161b6e2517098c457c314 0 1757502551024 7 connected
3aa39d945b99433a724aba322b3522cd975e5be9 192.168.70.20:6380@16380 slave 28c8ded8f4aa828c5a8566484aae881d62edea80 0 1757502553041 3 connected
f2a2030f94e724b51947d995f4fd79b324c67765 192.168.70.20:6381@16381 master - 0 1757502552000 0 connected
#看到多了一个6381端口的master
添加从节点
[root@master ~]# redis-cli --cluster add-node 192.168.70.20:6382 192.168.70.20:6379 --cluster-slave --cluster-master-id f2a2030f94e724b51947d995f4fd79b324c67765
#其中的长串字符对应为 192.168.70.20:6381
#查看
[root@master ~]# redis-cli
127.0.0.1:6379> cluster nodes
44c780fe83f33b89b360abed41e5798806eaadd2 192.168.70.20:6382@16382 slave f2a2030f94e724b51947d995f4fd79b324c67765 0 1757502718000 0 connected
28c8ded8f4aa828c5a8566484aae881d62edea80 192.168.70.22:6379@16379 master - 0 1757502717099 3 connected 10923-16383
1cd96a083b2eebc5cea5d0321e1a9b6ac920b57f 192.168.70.20:6379@16379 myself,master - 0 1757502716000 1 connected 0-5460
3efb6c4070e9faa0b36fa1ccbf3dde452953e7d4 192.168.70.21:6380@16380 slave 1cd96a083b2eebc5cea5d0321e1a9b6ac920b57f 0 1757502717000 1 connected
4fb00272746c7fe092d161b6e2517098c457c314 192.168.70.22:6380@16380 master - 0 1757502718107 7 connected 5461-10922
51d4c8f057354490773ab320fd2c9a5125a96c53 192.168.70.21:6379@16379 slave 4fb00272746c7fe092d161b6e2517098c457c314 0 1757502715000 7 connected
3aa39d945b99433a724aba322b3522cd975e5be9 192.168.70.20:6380@16380 slave 28c8ded8f4aa828c5a8566484aae881d62edea80 0 1757502719115 3 connected
f2a2030f94e724b51947d995f4fd79b324c67765 192.168.70.20:6381@16381 master - 0 1757502719000 0 connected
因为集群中增加了新节点,需要对现有数据重新进行分片操作。
#将192.168.70.22:6379的插槽分给192.168.70.20:6381一百个
[root@master ~]# redis-cli --cluster reshard 192.168.70.20:6379 --cluster-from 28c8ded8f4aa828c5a8566484aae881d62edea80 --cluster-to f2a2030f94e724b51947d995f4fd79b324c67765 --cluster-slots 100 --cluster-yes --cluster-timeout 5000 --cluster-pipeline 10 --cluster-replace
#查看
[root@master ~]# redis-cli
127.0.0.1:6379> cluster nodes
集群缩容
先将被删除的Redis node上的槽位迁移到集群中的其他Redis node节点上,然后再将其删除,如果一个Redis node节点上的槽位没有被完全迁移,删除该node的时候会提示有数据且无法删除。
#查看被迁移的节点上有多少插槽
[root@master ~]# redis-cli --cluster check 192.168.70.20:6380
192.168.70.22:6379 (28c8ded8...) -> 1 keys | 5361 slots | 1 slaves.
192.168.70.22:6380 (4fb00272...) -> 0 keys | 5462 slots | 1 slaves.
192.168.70.20:6379 (1cd96a08...) -> 0 keys | 5461 slots | 1 slaves.
192.168.70.20:6381 (f2a2030f...) -> 0 keys | 100 slots | 1 slaves.
#迁移
[root@master ~]# redis-cli --cluster reshard 192.168.70.20:6380 --cluster-from f2a2030f94e724b51947d995f4fd79b324c67765 --cluster-to 28c8ded8f4aa828c5a8566484aae881d62edea80 --cluster-slots 100
#在先删除从节点,然后主主节点
[root@master ~]# redis-cli --cluster del-node 192.168.70.20:6381 f2a2030f94e724b51947d995f4fd79b324c67765
>>> Removing node f2a2030f94e724b51947d995f4fd79b324c67765 from cluster 192.168.70.20:6381
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.
[root@master ~]# redis-cli --cluster del-node 192.168.70.20:6382 44c780fe83f33b89b360abed41e5798806eaadd2
>>> Removing node 44c780fe83f33b89b360abed41e5798806eaadd2 from cluster 192.168.70.20:6382
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.
82 44c780fe83f33b89b360abed41e5798806eaadd2
>>> Removing node 44c780fe83f33b89b360abed41e5798806eaadd2 from cluster 192.168.70.20:6382
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.