Redis Cluster高可用集群搭建

笔者前面的博客分别介绍了Redis“主从复制”和“哨兵模式”服务的搭建,但是这两种服务还有一些问题没有解决,例如:

  • 单台Master写性能存在瓶颈
  • 数据无法分布式存储,单机内存有限

为了解决这些问题,Redis还提供了一种扩展性更强,可用性更好的Cluster集群方案。

Redis Cluster集群是什么?

Redis Cluster集群是一个由多个主从节点集群组成的分布式服务器群,它具有数据复制、高可用和数据分片存储的特性。
Redis Cluster集群不需要Sentinel哨兵也能完成节点移除和故障转移的功能。
需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,官方文档称可以线性扩展到1000个节点。
Redis Cluster集群的性能和可用性均优于“主从复制”和“哨兵模式”,配置也非常简单,更加适用于企业服务。

Cluster集群原生搭建

架构图
Redis Cluster高可用集群搭建_第1张图片
如上图所示,本次环境搭建3台Master,6台Slave。
Redis默认有16384个槽位,必须将这些槽位全部分配到Master中,否则会导致有些数据无法写入。
当有数据写入时,Redis使用CRC16算法将Key计算得到一个数字,类似于哈希码,将值与16384取模确定一个槽位,然后将数据写入到该槽位所在的Master节点。
Master写入数据后,会将数据同步到对应的Slave节点,即主从复制。
单台Master宕机后,Redis会自动进行故障转移,将Master下的一台Slave晋升为新Master。

实际应用中Redis节点需要部署到不同的物理机,笔者没有那么多的物理机,遂用单机的不同端口跑多个Redis节点服务。
测试环境:8001、8004、8007为Master。
8002、8003 slaveof 8001
8005、8006 slaveof 8004
8008、8009 slaveof 8007

几个基本命令

  • cluster info:查看集群信息
  • cluster nodes:查看节点信息
  • cluster meet ip port:将节点加入到工作集群
  • cluster keyslot key:计算Key的CRC16算法结果值
  • cluster addslots slot (槽下标):设置槽位
  • cluster replicate (master node-id):将节点设为指定Master的Slave

1、创建配置文件

拷贝Redis提供的默认配置文件,做一些常规修改(不赘述),搭建集群主要修改如下:

# 启用Cluster集群
cluster-enabled yes
# 保存集群信息的文件,每台节点都会同步集群信息并保存到各自的文件中
cluster-config-file nodes-8001.conf

2、依次启动Master节点

redis-server 8001/redis.conf 
redis-server 8004/redis.conf 
redis-server 8007/redis.conf

查看服务是否启动成功:
在这里插入图片描述
注意:这时候节点是无法写入数据的,因为没有设置哈希槽Slot,数据不知道该写入哪个节点,如下图:
在这里插入图片描述

3、集群meet

集群Master节点都虽然已经启动,但是目前节点之间互相还没有关联,互相都不认识,还没有形成集群。
查看集群信息,发现只有自身节点。
在这里插入图片描述

cluster meet ip port

通过该命令来让节点互相认识,并形成网状结构。
cluster meet 192.168.1.120 8004
cluster meet 192.168.1.120 8007

重新查看集群信息
在这里插入图片描述

4、启动Slave节点

除了Master,还得有Slave节点,否则无法实现高可用和数据备份。
启动Slave节点和Master步骤一样,这里不再赘述,启动完成后如下图所示:
Redis Cluster高可用集群搭建_第2张图片

5、主从分配

启动的节点若不做配置,默认都是Master,需要进行主从分配。

主从分配之前,需要将新启动的Slave节点meet一下,先让节点加入到集群。

cluster replicate node-id通过该命令来分配主从。
登录到Slave节点执行该命令,node-id为Master节点的id。

查看节点的node-id
Redis Cluster高可用集群搭建_第3张图片
将Slave节点分配到Master节点下。(演示8002、8003,其他不赘述)

redis-cli -p 8002 cluster replicate 22bbad3e9cd6065861f13b95cef5d437483c6360
OK
redis-cli -p 8003 cluster replicate 22bbad3e9cd6065861f13b95cef5d437483c6360
OK

全部分配完成后,如下图所示:
Redis Cluster高可用集群搭建_第4张图片

6、指派槽位

前面已经说过,没有为Master指定Slot槽位,是无法写入数据的。

cluster keyslot key该命令可以查看指定Key的CRC16计算的值。

Redis集群默认有16384个槽位,现有3台Master节点,平均进行分配。

  • Master-8001:0~5461
  • Master-8004:5462~10922
  • Master-8007:10923~16383

cluster addslots slot [槽位下标]该命令用来设置节点的槽位。

为了快速分配,写了个Shell脚本,如下:

#!/bin/sh
# 读取端口
echo -n 'port:'
read port
#槽位起始下标
echo -n 'start:'
read s
#槽位结束下标
echo -n    'end:'
read e
#循环设置槽位
for i in $(seq $s $e)
do
redis-cli -h 192.168.1.120 -p $port cluster addslots $i
echo redis-cli -h 192.168.1.120 -p $port cluster addslots $i;
done

运行脚本,批量设置槽位,设置完成后查看如下图:
Redis Cluster高可用集群搭建_第5张图片

7、集群测试

指派好槽位后,集群的搭建工作就算完成了。
现在可以正常写入数据了:
Redis Cluster高可用集群搭建_第6张图片
以集群的模式去连接:redis-cli -c
Redis Cluster高可用集群搭建_第7张图片
Jedis集群写入数据

Set<HostAndPort> hostAndPorts = new HashSet<>(3);
hostAndPorts.add(new HostAndPort("192.168.1.120", 8001));
hostAndPorts.add(new HostAndPort("192.168.1.120", 8004));
hostAndPorts.add(new HostAndPort("192.168.1.120", 8007));
JedisCluster jedisCluster = new JedisCluster(hostAndPorts);
for (int i = 0; i < 100; i++) {
	jedisCluster.set(String.valueOf(i), String.valueOf(i));
}
jedisCluster.close();

100个数据会被分散到3台Master里分片存储。

redis-cli快速搭建

上面记录的是自己原生搭建Redis Cluster集群的方式,稍微有点麻烦,Redis提供了一种更简单的方式来快速搭建。
redis-cli --cluster help命令会显示一些搭建集群的帮助信息。

快速搭建集群

redis-cli --cluster create host1:port1 ... hostN:portN --cluster-replicas [主从节点的比例]

redis-cli --cluster create 192.168.1.120:8001 192.168.1.120:8002 192.168.1.120:8003 192.168.1.120:8004 192.168.1.120:8005 192.168.1.120:8006 192.168.1.120:8007 192.168.1.120:8008 192.168.1.120:8009 --cluster-replicas 2

查看节点信息
Redis Cluster高可用集群搭建_第8张图片
redis-cli工具一条命令即可快速搭建集群,自动分配主从节点,分配槽位。

集群扩容

如果集群的性能达不到预期,可以进行扩容。
Redis Cluster支持线性扩容,官方宣称可以扩容至1000个节点。

扩容命令:redis-cli --cluster add-node new_host:new_port 存在的IP:存在的端口
节点默认作为Master被添加,如果需要指明为Slave,加参数:--cluster-slave --cluster-master-id Master的node-id

例如将7001、7002、7003添加到集群。

# 7001Master
redis-cli --cluster add-node 192.168.1.120:7001 192.168.1.120:8001
# 7002作为7001的Slave
redis-cli --cluster add-node 192.168.1.120:7002 192.168.1.120:7001 --cluster-slave --cluster-master-id f8bbd9f97db60f4b00a80a2bdcf555e95559582a
# 7003作为7001的Slave
redis-cli --cluster add-node 192.168.1.120:7003 192.168.1.120:7001 --cluster-slave --cluster-master-id f8bbd9f97db60f4b00a80a2bdcf555e95559582a

节点添加后,可以通过cluster nodes命令查看节点信息。

迁移槽位和数据

扩容的Master节点没有默认没有槽位,是不会被写入数据的,需要进行槽位的分配和数据的迁移。
槽位和Key是绑定的,槽位重新分配意味着数据需要重新迁移。

命令:redis-cli --cluster reshard ip port

例如:给新加入的7001分配4096个槽位。

redis-cli --cluster reshard 192.168.1.120:8001
How many slots do you want to move (from 1 to 16384)? 4096 #输入分配的槽位数量
What is the receiving node ID? #输入要分配给哪台节点的node-id
Source node #1: all #要从哪些节点取出槽位分配给新节点?all表示从所有节点中平均取

分配完成后查看槽位分配信息:
Redis Cluster高可用集群搭建_第9张图片

集群缩容

如果集群的性能过剩,也可以选择移除部分节点,Redis也都是支持的。

迁移槽位和数据
注意:移除节点前,需要将该节点的槽位和数据重新分配到其他Master节点!
如果不这么做,会导致数据丢失,以及部分数据写入失败。

将7001的槽位和数据分配到8001上:
–cluster-from 来自哪台节点
–cluster-to 分配到哪台节点去
-cluster-slots 迁移的槽位数量

# 移除7001的槽位和数据
redis-cli --cluster reshard 192.168.1.120:8001 --cluster-from f8bbd9f97db60f4b00a80a2bdcf555e95559582a --cluster-to 201ce4d928c795384bbfde39215065d2eb41592e --cluster-slots 4096

槽位和数据迁移完毕后,就可以移除节点了。
命令:redis-cli --cluster del-node host:port node_id
例如:移除刚添加的7001节点。

# 集群移除节点
redis-cli --cluster del-node 192.168.1.120:8001 f8bbd9f97db60f4b00a80a2bdcf555e95559582a

节点移除后,Redis会自动将其SHUTDOWN

你可能感兴趣的:(后端)