1.写在前面
前面的博客,我们介绍缓存的三大问题中的缓存的穿透的问题,今天的原本打算介绍缓存击穿和缓存雪崩的问题,但是这儿我们需要一些前置的知识,就是集群的知识,于是我今天打算先介绍下Redis的集群的一些知识。
2.Redis集群的演变的过程
每一种技术出现都有它的历史的原因,学习一门的技术,我们不能只能简简单单的了解技术如何使用,以及技术的底层的原理,我们还要适当的了解下这样的技术的演变的过程。
2.1单机版
核心技术:数据持久化
持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。
单机的问题:
- 单机故障
- 容量瓶颈
- qps瓶颈
于是演变出来的主从复制的机制
2.2主从复制
复制是高可用Redis的基础,哨兵和集群都是在复制基础上实现高可用的。复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷是故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。
2.3哨兵
在复制的基础上,哨兵实现了自动化的故障恢复。缺陷是写操作无法负载均衡;存储能力受到单机的限制。
2.4集群
通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。
上面的方案,今天我只打算将集群的方案,至于其他的方案,我打算后面再讲。
3.Redis cluster高可用集群
3.1Redis cluster集群是什么?
redis cluster集群是一个由多个主从节点群组成的分布式服务器群,它具有复制、高可用和分片特性。Redis cluster集群不需要sentinel哨兵也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,据官方文档称可以线性扩展到1000节点。redis cluster集群的性能和高可用性均优于之前版本的哨兵模式,且集群配置非常简单。
3.2Redis cluster集群如何搭建?
至于怎么搭建,主要照顾多个版本,针对多种版本,这儿我就打算多介绍几种方法。
不管是那种方法,我们都要准备好集群的机器,由于我这个没有很多的机器,所以这儿就在一台机器上实现一个伪集群,首先创建8个文件夹,我这儿打算先用6台机器搭建一个简单的集群,具体的如下:
然后先拷贝一个redis.conf
文件到redis7000
的目录,然后修改对应的配置文件如下:我这儿只修改有关集群的配置,其他的可以看我之前的博客,我这儿就不做过多的赘述。
# 指定Redis的端口
port 6379
# 修改为 port 7000
# 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
pidfile /var/run/redis_6379.pid
# 修改为 pidfile /var/run/redis_7000.pid
# 日志文件的位置,当指定为空字符串时,为标准输出,如果redis已守护进程模式运行,那么日志将会输出到 /dev/null 。
logfile ""
# 修改为 logfile "/myredis/redis7000/redis.log"
# dbfilename文件存放目录。必须是一个目录,aof文件也会保存到该目录下。
dir ./
# 修改为 dir /myredis/redis7000
# 当master服务设置了密码保护时,slave服务连接master的密码
# masterauth <master-password>
# 修改为 masterauth 123456
# 是否开启cluster集群模式 如果配置yes则开启集群功能,此redis实例作为集群的一个节点,否则,它是一个普通的单一的redis实例。
# cluster-enabled yes
# 修改为 cluster-enabled yes
# 虽然此配置的名字叫"集群配置文件",但是此配置文件不能人工编辑,它是集群节点自动维护的文件,
# 主要用于记录集群中有哪些节点、他们的状态以及一些持久化参数等,方便在重启时恢复这些状态。通常是在收到请求之后这个文件就会被更新。
# cluster-config-file nodes-6379.conf
# 修改为 cluster-config-file nodes-7000.conf
# 表示当负责一个插槽的主库下线且没有相应的从库进行故障恢复时,是否整个集群不可用?
# cluster-require-full-coverage yes
# 修改为 cluster-require-full-coverage yes
# 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭
# requirepass foobared
# 修改为 requirepass 123456
# 如果将"cluster-replica-no-failover"设置为yes,那么该集群从节点不会参与自动故障转移过程,但是可以手动强制执行故障转移
# cluster-replica-no-failover no
# 修改为 cluster-replica-no-failover no
主要配置上面的一些配置项,配置完,然后执行如下的命令
sed 's/7000/7001/g' redis7000/redis.conf > redis7001/redis.conf
sed 's/7000/7002/g' redis7000/redis.conf > redis7002/redis.conf
sed 's/7000/7003/g' redis7000/redis.conf > redis7003/redis.conf
sed 's/7000/7004/g' redis7000/redis.conf > redis7004/redis.conf
sed 's/7000/7005/g' redis7000/redis.conf > redis7005/redis.conf
sed 's/7000/7006/g' redis7000/redis.conf > redis7006/redis.conf
sed 's/7000/7007/g' redis7000/redis.conf > redis7007/redis.conf
这儿所有的环境的因素都准备好了。然后就开始我们的后面的操作了。具体的如下:
方法一:原生搭建
-
配置开启cluster节点,前面的操作已经准备好了,这儿就不赘述了。
-
meet
cluster meet ip port
-
指派槽
查看crc16 算法算出key的槽位命令 cluster keyslot key
16384/3 0-5461 5462-10922 10923-16383
16384/4 4096cluster addslots slot(槽位下标)
-
分配主从
cluster replicate node-id
由于这种方法搭建起来比较麻烦,我这儿就不演示,一般不用了。
方法二:使用redis提供的rb脚本
-
环境的准备,前面的已经介绍了,这儿也不做过多的赘述了。
-
由于 redis集群需要使用 ruby命令,所以我们需要安装 ruby(redis5.0之后省略)
yum install ruby yum install rubygems gem install redis --version 3.0.0 #(安装redis和 ruby的接囗)
-
分别启动6个redis实例,然后检查是否启动成功
/usr/local/redis/bin/redis-server /myredis/redis800*/redis.conf ps -ef | grep redis #查看是否启动成功
-
在redis3的安装目录下执行 redis-trib.rb命令创建整个redis集群
cd /opt/redis/src ./redis-trib.rb create --replicas 1 192.168.181.6:7000 192.168.181.6:7001 192.168.181.6:7002 192.168.181.6:7003 192.168.181.6:7004 192.168.181.6:7005
-
验证集群
连接任意一个客户端即可:./redis-cli -c -h -p (-c表示集群模式,指定ip地址和端口号)如:/usr/local/bin/redis-cli -c -h 192.168.181.6 -p 7000 -a 123456
进行验证:
cluster info
(查看集群信息)、cluster nodes
(查看节点列表)进行数据操作验证
关闭集群则需要逐个进行关闭,使用命令:/usr/local/bin/redis-cli -c -h 192.168.181.6 -p 7000 shutdown
方法三:使用Redis自带的命令
走来还是分别启动每个Redis的服务。然后执行如下的命令创建集群。
具体的命令如下:
/usr/local/bin/redis-cli --cluster create 192.168.181.6:7000 192.168.181.6:7001 192.168.181.6:7002 192.168.181.6:7003 192.168.181.6:7004 192.168.181.6:7005 --cluster-replicas 1 -a 123456
注意--cluster-replicas 1
这个表示主机和从机的比例,这儿表示就是1:1,主机和从机都是1台,但是主机至少需要三台,所以这儿6台刚刚好。
我们先分别启动所以的Redis的服务,具体的如下:
可以看到我们的6台Redis的服务已经启动了,然后就可以开始搭建我们的集群了,具体的如下:
输入yes
,然后继续执行。具体的如下:
这样就搭建成功了,我们可以验证一下,具体的如下:
可以看到我们的集群搭建成功了。很nice!
如果这个时候我们的机器要进行扩容,或者我们减少机器该怎么办?不用慌,Redis给我们提供了对应的解决办法,就由我一一道来吧。
3.3扩容集群
扩容集群我们需要明确我们需要做什么?首先就是先启动两台Redis的服务,具体的如下:
可以发现我们的要加的两台的Redis的服务已经启动起来,那么我们怎么将他们加入到集群中去呢?具体的命令的如下:
/usr/local/bin/redis-cli --cluster add-node new_host:new_port existing_host:existing_port --cluster-slave --cluster-master-id <arg>
主机的添加方法
/usr/local/bin/redis-cli --cluster add-node 192.168.181.6:7006 192.168.181.6:7000
我们先添加主机,然后通过对应的命令查看主机的–cluster-master-id,具体的如下:
从机的添加方法
/usr/local/bin/redis-cli --cluster add-node 192.168.181.6:7007 192.168.181.6:7000 --cluster-slave --cluster-master-id 5884ffe0f8ab2c6a9d5194ff8c92a05f81cbaae6 -a 123456
执行完再次查看节点,具体的如下:
可以看到我们新加的两台Redis服务已经加入到集群中去了,但是新加的机器似乎没有给它分片,不然这两台和摆设差不多,所以我们这儿要给它分片,具体的操作如下:
#/usr/local/bin/redis-cli --cluster reshard host:port
/usr/local/bin/redis-cli --cluster reshard 192.168.181.6:7006 -a 123456
输入要分配多少个槽位,这儿输入900,然后回车,如下:
这儿输入接收节点ID,输入192.168.181.6:7006
的节点的ID,然后回车,如下:
all表示从所有的节点的平均分配过来,这儿直接从其他的节点平均分配过来吧!done表示直接结束,这儿也可以指定对应的节点分配到192.168.181.6:7006
上来,我们这儿为了简单,就直接输入all吧!
输入yes,然后继续。这样就分配好了,然后我们在来查看对应的节点信息,具体的如下:
可以发现我们插槽分配成功了,讲完了扩容,我们继续讲缩容。
3.4缩容集群
-
下线迁移槽
语法:redis-cli --cluster reshard --cluster-from 要迁出节点ID --cluster-to 接收槽节点ID --cluster-slots 迁出槽数量 已存在节点ip 端口
具体的命令如下:
/usr/local/bin/redis-cli --cluster reshard --cluster-from 5884ffe0f8ab2c6a9d5194ff8c92a05f81cbaae6 --cluster-to 6a7d6c50de8ddd29185146245ea15e4c1e94ed05 --cluster-slots 900 192.168.181.6 7000 -a 123456
输入yes,然后准备迁移。迁移完成后的节点的信息如下:
可以看到这个时候我们的
192.168.181.6:7006
上面的插槽已经完全迁移完,这个时候就可以做停机处理了。 -
忘记节点.关闭节点
语法: redis-cli --cluster del-node 已存在节点IP:端口 要删除的节点ID
具体的命令如下:
/usr/local/bin/redis-cli --cluster del-node 192.168.181.6:7000 5884ffe0f8ab2c6a9d5194ff8c92a05f81cbaae6 -a 123456 /usr/local/bin/redis-cli --cluster del-node 192.168.181.6:7000 4de8081381193ad2f59f7b8dc270837bf5e31494 -a 123456
分别忘记节点
192.168.181.6:7006
和192.168.181.6:7007
的节点,执行完节点的信息如下:
至此扩容和缩容就讲完了。
3.5cluster客户端
- moved重定向:指我们发送命令时,会对发送的key进行crc16算法,得到一个数字,然而我们连接的客户端并不是管理这个数字的范围,所以会返回错误并告诉你此key应该对应的槽位,然后客户端需要捕获此异常,重新发起请求到对应的槽位
- asx重定向:指在我们送发命令时,对应的客户端正在迁移槽位中,所以此时我们不能确定这个key是还在旧的节点中还是新的节点中
- smart客户端
- 从集群中选取一个可运行节点,使用cluster slots初始化槽和节点映射。
- 将cluster slots的结果映射到本地,为每个节点创建jedispool
- 准备执行命令
3.6故障转移
-
故障发现: 通过ping/pong消息实现故障发现(不依赖sentinel)
-
故障恢复
-
检查资格
每个从节点检查与主节点的断开时间,超过cluster-node-timeout * cluster-replica-validity-factor 时间取消资格
-
选择偏移量最大的替换主节点
当前从节点取消复制变为主节点(slaveof no one)
撤销以前主节点的槽位,给新的主节点
向集群广播消息,表明已经替换了故障节点
-
4.写在最后
本篇博客主要简单的介绍了下Redis的集群的搭建,以及集群的扩容和缩容等知识。