Redis Cluster实现多主写入

使用哨兵sentinel 只能解决Redis高可用问题,实现Redis的自动故障转移,但仍然无法解决Redis Master 单节点的性能瓶颈问题

为了解决单机性能的瓶颈,提高Redis 服务整体性能,可以使用分布式集群的解决方案

Redis 3.0 版本之后推出无中心架构的 Redis Cluster ,支持多个master节点并行写入和故障的自动转移 动能.

Redis Cluster 架构

10、Redis Cluster实现多主写入_Redis Cluster实现多主写入

Redis cluster 需要至少 3个master节点才能实现,slave节点数量不限,当然一般每个master都至少对应的有一个slave节点

如果有三个主节点采用哈希槽 hash slot 的方式来分配16384个槽位 slot

此三个节点分别承担的slot区间可以是如以下方式分配

节点M1 0-5460 
节点M2 5461-10922 
节点M3 10923-16383

每个key存储时,先经过哈希函数CRC16(key)得到一个整数,然后整数与16384取余,得到槽的数值, 然后找到对应的节点,将数据存放入对应的槽中.

集群通信
集群中节点之间的通信,保证了最多两次就能命中对应槽所在的节点.因为在每个节点中,都保存了其他节点的信息,知道哪个槽由哪个节点负责.这样即使第一次访问没有命中槽,但是会通知客户端, 该槽在哪个节点,这样访问对应节点就能精准命中.

10、Redis Cluster实现多主写入_Redis Cluster实现多主写入_02


1、节点A对节点B发送一个meet操作,B返回后表示A和B之间能够进行沟通
2、节点A对节点C发送meet操作,C返回后,A和C之间也能进行沟通.
3、然后B根据对A的了解,就能找到C,B和C之间也建立了联系.
4、直到所有节点都能建立联系.,这样每个节点都能互相知道对方负责哪些槽.

Redis集群部署架构说明

注意: 建立Redis Cluster 的节点需要清空数据

测试环境:3台服务器,每台服务器启动6379和6380两个redis 服务实例,适用于测试环境

生产环境:6台服务器,分别是三组master/slave,适用于生产环境

10、Redis Cluster实现多主写入_Redis Cluster实现多主写入_03

#集群节点 
10.0.0.100
10.0.0.101
10.0.0.102
10.0.0.103
10.0.0.104
10.0.0.105 
#预留服务器扩展使用 
10.0.0.106 
10.0.0.107
打通GUK验证,把安装脚本发送到各个主机

修改主机名
hostnamectl set-hostname node0
.
.
.
hostnamectl set-hostname node7

所有机器脚本编译安装redis

每个节点修改redis配置,必须开启cluster功能的参数

第一步:修改redis配置文件
[root@node0 ~]#vim /apps/redis/etc/redis.conf
手动修改redis.conf配置文件
bind 0.0.0.0
masterauth 123456      #建议配置,否则后期的master和slave主从复制无法成功,还需再配置
requirepass 123456     
cluster-enabled yes    #取消此行注释,必须开启集群,开启后redis进程会有cluster标识
cluster-config-file nodes-6379.conf #取消此行注释,此为集群状态数据文件,记录主从关系及slot范围信息,由redis cluster 集群自动创建和维护
cluster-require-full-coverage no  #默认值为yes,设为no可以防止一个节点不可用导致整个cluster不可用

#如果是编译安装可以执行下面操作更改
sed -i.bak  -e '/masterauth/a masterauth 123456'  -e '/# cluster-enabled yes/a cluster-enabled yes' -e '/# cluster-config-file nodes-6379.conf/a cluster-config-file nodes-6379.conf' -e '/cluster-require-full-coverage yes/c cluster-require-full-coverage no' /apps/redis/etc/redis.conf

重启所有节点
[root@node0 ~]#systemctl restart redis
[root@node0 ~]#ps aux
redis       17:36   0:00 /apps/redis/bin/redis-server 0.0.0.0:6379 [cluster]
出现[cluster]就成功了,并额外增加一个集群内部通讯的端口16379

集群功能只支持0号数据库

创建集群

第二步:命令redis-cli的选项 --cluster-replicas 1  表示每个master对应一个slave节点
在任何一台机器上执行以下命令
redis-cli -a 123456  --cluster create 10.0.0.100:6379   10.0.0.101:6379    10.0.0.102:6379   10.0.0.103:6379   10.0.0.104:6379   10.0.0.105:6379  --cluster-replicas 1                                          #--cluster-replicas 1 每个主节点配套1个从节点
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 10.0.0.104:6379 to 10.0.0.100:6379
Adding replica 10.0.0.105:6379 to 10.0.0.101:6379
Adding replica 10.0.0.103:6379 to 10.0.0.102:6379
M: 26ab5f3fd31ef3972af895d953d6f66227de8217 10.0.0.100:6379
   slots:[0-5460] (5461 slots) master
M: f70ab5aedde31319ba21fe6e44751bfd6a2f5bb0 10.0.0.101:6379
   slots:[5461-10922] (5462 slots) master
M: 08d6a31b426a2a7b8b76d829b1b547ba96e0da29 10.0.0.102:6379
   slots:[10923-16383] (5461 slots) master
S: a205e64ddb338537d6873324d2f5f4c38bd6783b 10.0.0.103:6379
   replicates 08d6a31b426a2a7b8b76d829b1b547ba96e0da29
S: dcaee05eb2e63ca4a8a4046124425108c05d6f2c 10.0.0.104:6379
   replicates 26ab5f3fd31ef3972af895d953d6f66227de8217
S: afcaf762f2d5ee4944891a1bd6c77b40268778cd 10.0.0.105:6379
   replicates f70ab5aedde31319ba21fe6e44751bfd6a2f5bb0
Can I set the above configuration? (type 'yes' to accept): yes
输入yes后,分槽位
>>> Performing Cluster Check (using node 10.0.0.100:6379)
M: 26ab5f3fd31ef3972af895d953d6f66227de8217 10.0.0.100:6379
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: dcaee05eb2e63ca4a8a4046124425108c05d6f2c 10.0.0.104:6379
   slots: (0 slots) slave
   replicates 26ab5f3fd31ef3972af895d953d6f66227de8217
M: 08d6a31b426a2a7b8b76d829b1b547ba96e0da29 10.0.0.102:6379
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
M: f70ab5aedde31319ba21fe6e44751bfd6a2f5bb0 10.0.0.101:6379
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: a205e64ddb338537d6873324d2f5f4c38bd6783b 10.0.0.103:6379
   slots: (0 slots) slave
   replicates 08d6a31b426a2a7b8b76d829b1b547ba96e0da29
S: afcaf762f2d5ee4944891a1bd6c77b40268778cd 10.0.0.105:6379
   slots: (0 slots) slave
   replicates f70ab5aedde31319ba21fe6e44751bfd6a2f5bb0
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
第三步:查看主从信息
[root@node0 ~]#cat /apps/redis/data/nodes-6379.confdcaee05eb2e63ca4a8a4046124425108c05d6f2c 10.0.0.104:6379@16379 slave 26ab5f3fd31ef3972af895d953d6f66227de8217 0 1667382573000 1 connected
08d6a31b426a2a7b8b76d829b1b547ba96e0da29 10.0.0.102:6379@16379 master - 0 1667382573000 3 connected 10923-16383
f70ab5aedde31319ba21fe6e44751bfd6a2f5bb0 10.0.0.101:6379@16379 master - 0 1667382573354 2 connected 5461-10922
26ab5f3fd31ef3972af895d953d6f66227de8217 10.0.0.100:6379@16379 myself,master - 0 1667382571000 1 connected 0-5460
a205e64ddb338537d6873324d2f5f4c38bd6783b 10.0.0.103:6379@16379 slave 08d6a31b426a2a7b8b76d829b1b547ba96e0da29 0 1667382570326 3 connected
afcaf762f2d5ee4944891a1bd6c77b40268778cd 10.0.0.105:6379@16379 slave f70ab5aedde31319ba21fe6e44751bfd6a2f5bb0 0 1667382574364 2 connected
vars currentEpoch 6 lastVoteEpoch 0

[root@node0 ~]#redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> role
1) "master"
2) (integer) 8582
3) 1) 1) "10.0.0.104"
      2) "6379"
      3) "8582"
集群写入数据

写入数据,先经过哈希函数CRC16(key)得到一个整数,然后整数与16384取余,得到槽的数值, 然后找到对应的节点,将数据存放入对应的槽中. -c是以集群模式链接

[root@node0 ~]#redis-cli -a 123456 -c
127.0.0.1:6379> set k1 v1
-> Redirected to slot [12706] located at 10.0.0.102:6379
OK
10.0.0.102:6379> get k1
"v1"
加-c能写能查,但是keys *只能查到当前节点主从复制的数据,并且不支持mset 多keys写入
且所有的操作读和写都发生在主节点上,备用节点起不到性能分担的效果,就是主坏了,从节点能变成主

模拟故障实现故障转移

模拟node0节点出故障,需要相应的数秒故障转移时间,去node0对应的从节点上观察从节点状态
[root@node0 ~]#systemctl stop redis
[root@node4 ~]#redis-cli -a 123456
127.0.0.1:6379> role
1) "master"
2) (integer) 10848
3) (empty array)
成为主节点边可查可写了,

查看集群信息,显示100节点失败
[root@node4 ~]#cat /apps/redis/data/nodes-6379.conf
26ab5f3fd31ef3972af895d953d6f66227de8217 10.0.0.100:6379@16379 master,fail

恢复node0节点

[root@node0 ~]#systemctl start redis
查看集群信息
[root@node0 ~]#cat /apps/redis/data/nodes-6379.conf
node0自动变为node4的从节点了

python序实现Redis集群访问

范例

[root@ubuntu2004 ~]#apt -y install python3-pip
[root@ubuntu2004 ~]#pip3 install redis-py-cluster

[root@ubuntu2004 ~]#cat redis_cluster_test.py
#!/usr/bin/env python3
from rediscluster import RedisCluster
startup_nodes = [
    {"host":"10.0.0.100", "port":6379},
    {"host":"10.0.0.101", "port":6379},
    {"host":"10.0.0.102", "port":6379},
    {"host":"10.0.0.103", "port":6379}, 
    {"host":"10.0.0.104", "port":6379}, 
    {"host":"10.0.0.105", "port":6379}
]
redis_cnotallow= RedisCluster(startup_nodes=startup_nodes,password='123456', decode_respnotallow=True) 

for i in range(0, 10000):
    redis_conn.set('key'+str(i),'value'+str(i))
    print('key'+str(i)+':',redis_conn.get('key'+str(i)))
    
[root@ubuntu2004 ~]#python3 redis_cluster_test.py  
...... 
key9998: value9998
key9999: value9999

验证数据(数据分在三个主节点上)
[root@node0 ~]#redis-cli -a 123456
10.0.0.101:6379> DBSIZE 
(integer) 3331
目前三主三从单个节点的性能不如原来一个节点的性能,因为集群要CRC校验取值,数据不在当前节点,还要重新发请求进行访问。