20200610 千锋教育 Redis 5. Redis 高可用
Redis 高可用
单机 Redis 可能存在的问题
一般来说,要将 Redis 运用于工程项目中,只使用一台 Redis 是万万不能的,原因如下:
- 从结构上,单个 Redis 服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大;(容错性)
- 从容量上,单个 Redis 服务器内存容量有限,就算一台 Redis 服务器内容容量为 256G,也不能将所有内容用作 Redis 存储内存,一般来说,单台 Redis 最大使用内存不应该超过 20G。
单机 Redis 存在的问题:
- 内存容量有限
- 处理能力有限
- 无法高可用。
主从复制
简介
应用场景:电子商务网站上的商品,一般都是一次上传,无数次浏览的,说专业点也就是”多读少写”
主从复制:一个 Redis 服务可以有多个该服务的复制品,这个 Redis 服务称为 Master ,其它复制称为 Slaves
将一台 Redis 服务器作主库(Matser),其他 Redis 作为从库(Slave),主库只负责写数据,每次有数据更新都将更新的数据同步到它所有的从库,而从库只负责读数据。这样一来,就有了两个好处:
- 读写分离,不仅可以提高服务器的负载能力,并且可以根据读请求的规模自由增加或者减少从库的数量
- 数据被复制成了了好几份,就算有一台机器出现故障,也可以使用其他机的数据快速恢复。
需要注意的是:在 Redis 主从模式中,一台主库可以拥有多个从库,但是一个从库只能隶属于一个主库
Redis 主从复制配置
在 Redis 中,要实现主从复制架构非常简单,只需要在从数据库的配置文件中加上如下命令即可:
-
主数据库不需要任何配置,创建一个从数据库
redis.slave.conf
(配置文件信息)port 6380 replicaof 127.0.0.1 6379 或 slaveof 127.0.0.1 6379 masterauth 123456
-
启动从数据库:
./bin/redis-server ./redis.slave.conf
-
登录到从服务客户端
./bin/redis-c1i -p 6380 ## 通过 info 命令查看主 Redis 状态 info
-
测试
在主 Redis 中添加内容,在从 Redis 中查看是否成功同步
哨兵模式
简介 Redis-Sentinel(哨兵模式)是高可用解决方案,当 Redis 在做 master-slave 的高可用方案时,假如 master 宕机了, Redis 本身(以及其很多客户端)都没有实现自动进行主备切换,而 Redis-Sentinel 本身也是独立运行的进程,可以部署在其他与 Redis 集群可通讯的机器中监控 Redis 集群。
有了主从复制的实现之后,我们如果想从服务器进行监控,那么在 Redis 2.6 以后提供了一个哨兵机制,并在 2.8 版本以后功能稳定起来。
哨兵:顾名思义,就是监控 Redis 系统的运行状况
哨兵模式的特点:
- 不时地临控 Redis 否按照预期良好地运行
- 如果发现某个 Redis 节点运行出现状况,能够通知另外一个进程(例如它的客户端)
- 能够进行自动切换。当一个 master 节点不可用时,能够选出 master 的多个 slave(如果有超过一个 slave 的话)中的一个来作为新的 master ,其它的 slave 节点会将它所追随的 master 的地址改为被提升为 master 的 slave 的新地址
- 哨兵为客户端提供服务发现,客户端链接哨兵,哨兵提供当前 master 的地址然后提供服务,如果出现切换,也就是 master 挂了,哨兵会提供客户端一个新地址
哨兵模式存在的问题:耗费性能和资源
Redis Cluster 集群
简介
集群模式是实际使用最多的模式。Redis Cluster 是社区版推出的 Redis 分布式集群解決方案,主要解決 Redis 分布式方面的需求,如如,当遇到单机内存,并发和流量等瓶颈的时候,Redis Clusters 能起到很好的负载均衡的目的。
为什么使用 Redis-Cluster ?
为了在大流量访问下提供稳定的业务,集群化是存储的必然形态
未来的发展趋势肯定是云计算和大数据的紧密结合
只有分布式架构能满足要求
集群描述
Redis 集群搭建方案
- Twitter 开发的 twemproxy
- 豌豆英开发的 codis
- redis 官方的 redis-cluster
Redis 集群搭建的方式有多种,但从 Redis 3.0 之后支持 Redis-Cluster 集群,至少需要 3(Master)+ 3(Slave)才能建立集群。 Redis-Cluster 采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。
集群特点
- 所有的 Redis 节点彼此互联(PING-PONG 机制),内部使用二进制协议优化传输速度和带宽。
- 节点的 fail 是通过集群中超过半数的节点检测失效时才生效。
- 客户端与 Redis 节点直连,不需要中间 proxy 层,客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
- Redis-Cluster 把所有的物理节点映射到 [0-16383] slot 上(不一定是平均分配),cluster 负责维护
- Redis 集群预分好 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时, Redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个key 都会对应一个编号在 0-16383 之间的哈希槽,Redis 会根据节点数量大致均等的将哈希槽映射到不同的节点
Redis Cluster 容错
容错性,是指软件检测应用程序所运行的软件或硬件中发生的错误并从错误中恢复的能力,通常可以从系统的可靠性、可用性、可测性等几个方面来衡量
什么时候判断 master 不可用?
投票机制。投票过程是集群中所有 master 参与,如果半数以上 master 节点与 master 节点通信超时(cluster-node-timeout)认为当前 master 节点挂掉
什么时候整个集群不可用(cluster_state:fail)?
如果集群任意 master 挂掉,且当前 master 没有 slave。集群进入 fail 状态也可以理解成集群的 slot 映射 [0- 16383] 不完整时进入 fail 状态。如果集群超过半数以上 master 挂掉,无论是否有 slave,集群进入 fail 状态。
Redis Cluster 节点分配
Redis Cluster 采用虚拟槽分区,所有的键根据哈希函数映射到 0~16383 整数槽内,每个节点负责维护一部分槽以及槽所印映射的键值数据。
三个主节点分别是: A , B , C 三个节点,它们可以是一台机器上的三个端口,也可以是三台不同的服务器。那么,采用哈希槽( hash slot )的方式来分配 16384 个slot 的话,它们三个节点分别別承担的 slot 区间是
-
节点 A 覆盖 0 - 5460
-
节点 B 覆盖 5461 - 10922
-
节点 C 覆盖 10923 - 16383
Redis Cluster 集群搭建
Redis 集群需要至少要三个 master 节点,我们这里搭建三个 master 节点,并且给每个 master 再搭建一个 slave 节点,总共 6 个 Redis 节点,这里用一台机器(可以多台机器部署,修改一下 ip 地址就可以了)部署 6 个 Redis 实例,三主三从,搭建集群的步骤如下
## 1. 创建 Redis 集群节点安装目录
[root@hwjsLinux ~]# mkdir -p /usr/local/redis_cluster
## 2. 创建文件夹,7000-7005
[root@hwjsLinux ~]# cd /usr/local/redis_cluster/
[root@hwjsLinux redis_cluster]# mkdir 7000 7001 7002 7003 7004 7005
## 3. 复制原始 src 目录到当前目录下
[root@hwjsLinux redis_cluster]# cp -r /opt/redis/redis-5.0.0/src/ .
## 4. 复制原始 redis.conf 到 7000 内,并修改配置
[root@hwjsLinux redis_cluster]# cp /opt/redis/redis-5.0.0/redis.conf ./7000/
################
# 关闭保护模式用于公网访问
protected -mode no
port 7000
# 开启集群模式
cluster-enabled yes
cluster-config-file nodes-7000.conf
cluster-node-timeout 5000
# 后台启动
daemonize yes
pidfile /var/run/redis_7000.pid
logfile 7000.log
# dir /redis/data
# 此处绑定 ip 可以是阿里内网 ip 和本地 ip ,也可以直接注释掉该项
# bind 127.0.0.1
# 用于连接主节点密码
masterauth 123456
# 设置 redis 密码,各个节点请保持密码一致
requirepass 123456
################
## 5. 复制并修改其他5个 redis.conf
[root@hwjsLinux redis_cluster]# cp ./7000/redis.conf ./7001
[root@hwjsLinux redis_cluster]# vim ./7001/redis.conf
:%s/7000/7001/g
## 6. 依次启动 6 个节点
[root@hwjsLinux redis_cluster]# ./src/redis-server ./7000/redis.conf
### 查看启动的 Redis 进程
[root@hwjsLinux redis_cluster]# ps -ef | grep redis
## 7. 创建集群,Redis 5版本后通过 redis-cli 客户端命令来创建集群
[root@hwjsLinux redis_cluster]# ./src/redis-cli --cluster create -a 123456 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1
### 输入 yes 确认后,打印出以下信息,表示成功
[OK] All 16384 slots covered.
Redis Clusters 集群验证
在某台机器上:
## 连接集群的 7001 端口的节点
### 加参数 -c 可连接到集群 redis-cluster
./src/redis-cli -h 127.0.0.1 -c -p 7001 -a 123456
Redis-Cluster 在设计的时候,就考虑到了去中心化,去中间件,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而这些连接保持活跃,这样就保了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据
基本命令
## 通过以下命令来看看集群效果
info replication
cluster nodes
cluster info
每个 Redis 的节点都有一个 ID 值,此 ID 将被此特定 Redis 实例永久使用,以便实例在集群上下文中具有唯一的名称。每个节点都会记住使用此 ID 的每个其他节点,而不是通过 IP 或端口。 IP 地址和端口可能会发生变化,但唯一的节点标识符在节点的整个生命周期内都不会改变。我们简单地称这个标识符为节点 ID 。通过 cluster nodes
可以查看集群的节点 ID。
Redis Cluster 总结
Redis Cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会在从节点中选取一个来充当主节点,从而保证集群不会挂掉。
例如集群有 ABC 三个主节点,如果这 3个节点都没有加入从节点,如果 B 挂掉了,我们就无法访问整个集群了。A 和 C 的 slot 也无法访问。
所以我们在集群建立的时候,一定要为每个主节点都添加了从节点,比如像这样,集群包含主节点 A、B、C,以及从节点 A1、B1、C1,那么即使 B 挂掉系统也可以继续正确工作。
B1节点替代了B节点,所以 Redis 集群将会选择 B1 节点作为新的主节点,集群将会继续正确地提供服务。当B重新开启后,它就会变成 B1 的从节点。不过需要注意,如果节点 B 和 B1 同时挂了,Redis 集群就无法继续正确地提供服务了。
Redis Cluster 开启/关闭 集群
开启集群
/usr/local/redis_cluster/startCluster.sh
,文件内容如下:
./src/redis-server ./7000/redis.conf
./src/redis-server ./7001/redis.conf
./src/redis-server ./7002/redis.conf
./src/redis-server ./7003/redis.conf
./src/redis-server ./7004/redis.conf
./src/redis-server ./7005/redis.conf
./src/redis-cli --cluster create -a 123456 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1
## 为 startCluster.sh 赋权
chmod u+x startCluster.sh
## 执行脚本
sh startCluster.sh
关闭集群
/usr/local/redis_cluster/stopCluster.sh
,文件内容如下:
./src/redis-cli -c -h 127.0.0.1 -p 7000 -a 123456 shutdown
./src/redis-cli -c -h 127.0.0.1 -p 7001 -a 123456 shutdown
./src/redis-cli -c -h 127.0.0.1 -p 7002 -a 123456 shutdown
./src/redis-cli -c -h 127.0.0.1 -p 7003 -a 123456 shutdown
./src/redis-cli -c -h 127.0.0.1 -p 7004 -a 123456 shutdown
./src/redis-cli -c -h 127.0.0.1 -p 7005 -a 123456 shutdown
## 为 stopCluster.sh 赋权
chmod u+x stopCluster.sh
## 执行脚本
sh stopCluster.sh
## 查看 Redis 进程
ps -ef | grep redis