在Redis中,实现高可用的技术主要包括持久化、主从复制、哨兵和 Cluster集群
- 持久化:持久化是最简单的高可用方法(有时甚至不被归为高可用的手段),主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。
- 主从复制:主从复制是高可用Redis的基础,哨兵和集群都是在主从复制基础上实现高可用的。主从复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。
- 哨兵:在主从复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的限制。
- Cluster集群:通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案
redis持久化
1、持久化的功能:
Redis是内存数据库,数据都是存储在内存中,为了避免服务器断电等原因导致Redis进程异常退出后数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复
2、redis持久化方式
2.1、RDB持久化:周期性的把内存中的数据保存到磁盘上
可以分为:
- 手动触发
- 自动触发:save m n (假设 900 10 则表示900表内或者 10次语句执行,则触发RDB持久化)
- 特殊触发:当手动 关闭redis时,会进行RDB方式持久化 【shutdown 关闭时】【注:kill 删除进程 不会触发RDB】
架构图:
执行过程:
-
Redis父进程首先判断:当前是否在执行save,或bgsave/bgrewriteaof的子进程,如果在执行则bgsave命令直接返回。 bgsave/bgrewriteaof的子进程不能同时执行
-
创建子进程的过程fork创建的过程中会阻塞父进程,此时父进程将不能接受任何的请求操作
-
子进程创建完毕后会返回信息给父进程,此时父进程不再阻塞将可以使用其他命令响应
-
子进程的作用就是用来生成rdb文件,当rdb文件保存完毕后
-
子进程会信号通知父进程,父进程会更新统计信息
RDB的优缺点
缺点:
-
数据完整性不如AOF
-
RDB类似于快照(完备)
-
在进行备份时会阻塞进程
优点:
-
持久化的速度比较快(因为保存的是数据结果),再写入到 *.rdb持久化文件,并且会进行压缩,来减小自身的体积
-
集群中,redis主从复制 【从——>主】进行同步,默认先用RDB文件进行恢复操作,所以同步性能较高
2.2、AOF持久化(append only file): 从redis的操作日志记录中将执行的过程同步到磁盘中
可以分为:
- 手动触发:
- 自动触发:
1)always:每条语句,同步执行持久化有强一致性的要求的场景
2)no:不进行持久化
3)everysecond:每秒进行一次AOF持久化【建议使用,均衡型场景】
架构图:
执行流程包括:
-
命令追加:将redis的写命令追加到缓冲区 (内存)aof_buf
-
文件写入和文件同步:根据不同的同步策略将 aof_buf中内容同步到硬盘
-
文件重写:定期重写AOF文件,达到压缩的目的
1、aof文件重写需要用到 bgrewriteaof命令
父进程先判断有没有其他的子进程在运行,如果是bgrewriteaof的就直接返回,如果是bgsave,就等他执行完成,再去执行
2、如果没有其它子进程,父进程就会fork子进程,fork过程中父进程会阻塞,子进程创建好后会把信息通知父进程,父进程继续响应其他命令
3.1、redis会先将写入命令暂存在缓存区,根据fsync策略同步到硬盘里,fork后的数据也会被写入到旧的AOF文件里
3.2、父进程在fork完成后响应命令的同时记录在 aof_rewrite_buf当中
4、子进程根据内存快照,按照命令合并规则写入到新的AOF文件。
5.1、子进程写完新的AOF文件后,向父进程发信号,父进程更新统计信息
5.2、父进程把AOF重写缓存区的数据写入到新的AOF文件,这样就保证了新AOF文件所保存的数据库状态和服务器当前状态一致
5.3、新的AOF文件会替换旧的AOF文件
AOF的优缺点
缺点:
-
在执行语句一致的情况下,AOF备份的内容更大
RDB备份的内容较小,RDB备份的是结果,AOF备份的是语句
-
AOF消耗性能更大,占用磁盘越来越大(可以理解为MySQL的增量备份)
优点:
-
AOF数据的完整性比RDB更高
-
重写功能会对无效语句进行删除
为了节省AOF文件占用磁盘的空间
持久化过程:
aof的优先级高于rdb
RDB:
内存中——>写入磁盘中保存的方式
结果数据——>写入磁盘中保存数据对象
内存——>写入磁盘后,会进行压缩 来减小 *.rdb 文件的磁盘占用空间
AOF:
内存中——> append追加的缓存区 ——> 调用cpu资源写入到磁盘中
操作日志记录中的执行语句 ——> 追加到缓冲 ——> 调用cpu资源写入到磁盘中
内存——> 缓存 ——> 磁盘写入后 会周期性进行重写,跳过一些无效操作来保存数据
Redis 主从复制
是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master),后者称为从节点(Slave);数据的复制是单向的,只能由主节点到从节点。默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点
主从复制的作用:
-
数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
-
故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余
-
负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量
-
高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础
架构图:
主从复制流程:
1、从——>主发送sync同步数据请求
2、主 redis 会 fork子进程,然后生成一个 RDB文件(完全备份)的过程
2.1、客户端持续写入redis
3、RDB持久化完成后,主 redis 会将RDB文件和缓存起来的命令推送给从服务器
4、复制、推送完成后,主 redis 持续同步操作命令,利用 AOF(增量备份)持久化的功能
5、如果在下一台 redis模式接入主从复制群集之前,会持续利用 AOF 的方式同步数据 从redis
搭建Redis 主从复制
准备三台服务器:
Master节点: 192.168.86.11
Slave1节点: 192.168.86.22
Slave2节点: 192.168.86.33
systemctl stop firewalld
setenforce 0
安装好Redis后修改Redis配置文件(Master节点操作)【192.168.86.11】
vim /etc/redis/6379.conf redis.conf
bind 0.0.0.0 #70行,修改监听地址为0.0.0.0
daemonize yes #137行,开启守护进程
logfile /var/log/redis_6379.log #172行,指定日志文件目录
dir /var/lib/redis/6379 #264行,指定工作目录
appendonly yes #700行,开启AOF持久化功能
/etc/init.d/redis_6379 restart #重启服务
修改 Redis 配置文件(Slave节点操作)【192.168.86.22 和 192.168.86.33】
vim /etc/redis/6379.conf
bind 0.0.0.0 #70行,修改监听地址为0.0.0.0
daemonize yes #137行,开启守护进程
logfile /var/log/redis_6379.log #172行,指定日志文件目录
dir /var/lib/redis/6379 #264行,指定工作目录
replicaof 192.168.86.11 6379 #288行,指定要同步的Master节点IP和端口
appendonly yes #700行,开启AOF持久化功能
/etc/init.d/redis_6379 restart
验证:在Master节点上看日志 命令:tail -f /var/log/redis_6379.log
在Master节点上验证从节点 命令:redis-cli info replication
在master上创建key,在slave上查看
Redis 哨兵模式
当服务器宕机后,需要手动一台从机切换为主机,这需要人工干预,不仅费时费力而且还会造成一段时间内服务不可用。为了解决主从复制的缺点,就有了哨兵机制。哨兵的核心功能:在主从复制的基础上,哨兵引入了主节点的自动故障转移。
哨兵模式原理:
是一个分布式系统,用于对主从结构中的每服务器进行监控,当出现故障时通过投票机制选择新的Master并将所有slave连接到新的 Master。所以整个运行哨兵的集群的数量不得少于3个节点
哨兵的作用:
-
监控:哨兵会不断地检查主节点和从节点是否运作正常。
-
自动故障转移:当主节点不能正常工作时,哨兵会开始自动故障转移操作,它会将失效主节点的其中一个从节点升级为新的主节点,并让其它从节点改为复制新的主节点
-
通知 (提醒) :哨兵可以将故障转移的结果发送给客户端
哨兵结构由两部分组成:
-
哨兵节点:哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据
-
数据节点:主节点和从节点都是数据节点
架构图:
故障转移机制:
-
由哨兵节点定期监控发现主节点是否出现了故障
-
当主节点出现故障,此时哨兵节点会通过Raft算法(选举算法)实现选举机制共同选举出一个哨兵节点为leader,来负责处理主节点的故障转移和通知。所以整个运行哨兵的集群的数量不得少于3个节点
-
由leader哨兵节点执行故障转移,过程如下:
- 将某一个从节点升级为新的主节点,让其它从节点指向新的主节点
- 若原主节点恢复也变成从节点,并指向新的主节点
- 通知客户端主节点已经更换
哨兵对主从复制集群进行监控 监控对象:所有redis 数据节点
哨兵与哨兵之间进行互相监控 监控对象:哨兵彼此
监控的目的:
-
哨兵与哨兵之间的监控,目的是为了检测彼此的存活状态
-
哨兵监控所有 redis数据库的目的 为了实现自动故障切换
主节点的选举:
- 过滤掉不健康的(已下线的),没有回复哨兵 ping 响应的从节点。
- 选择配置文件中从节点优先级配置最高的。(replica-priority,默认值为100)
- 选择复制偏移量最大,也就是复制最完整的从节点
搭建Redis 哨兵模式 (在搭建完主从复制的基础上)
Master节点:192.168.86.11
Slave1节点:192.168.86.22
Slave2节点:192.168.86.33
systemctl stop firewalld
setenforce 0
修改 Redis 哨兵模式的配置文件(所有节点操作)
vim /opt/redis-5.0.7/sentinel.conf
protected-mode no #17行,关闭保护模式
port 26379 #21行,Redis哨兵默认的监听端口
daemonize yes #26行,指定sentinel为后台启动
logfile "/var/log/sentinel.log" #36行,指定日志存放路径
dir "/var/lib/redis/6379" #65行,指定数据库存放路径
sentinel monitor mymaster 192.168.86.11 6379 2 #84行,修改 指定该哨兵节点监控192.168.86.11:6379这个主节点,该主节点的名称是mymaster,最后的2的含义与主节点的故障判定有关:至少需要2个哨兵节点同意,才能判定主节点故障并进行故障转移
sentinel down-after-milliseconds mymaster 30000 #113行,判定服务器down掉的时间周期,默认30000毫秒(30秒)
sentinel failover-timeout mymaster 180000 #146行,故障节点的最大超时时间为180000(180秒)
启动哨兵模式,先启master,再启slave
cd /opt/redis-5.0.7/
redis-sentinel sentinel.conf &
查看哨兵信息 命令:redis-cli -p 26379 info Sentinel
故障模拟 :
先查看日志 命令:tail -f /var/log/sentinel.log
查看redis-server进程号 命令:ps -ef | grep redis
杀死 Master 节点上redis-server的进程号,再查看日志
Redis 群集模式
集群由多个节点(Node)组成,Redis的数据分布在这些节点中。集群中的节点分为主节点和从节点:只有主节点负责读写请求和集群信息的维护;从节点只进行主节点数据和状态信息的复制
集群的作用:
- 数据分区:数据分区(或称数据分片)是集群最核心的功能.集群将数据分散到多个节点,一方面突破了Redis单机内存大小的限制,存储容量大大增加;另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力
- 高可用:集群支持主从复制和主节点的自动故障转移(与哨兵类似);当任一节点发生故障时,集群仍然可以对外提供服务
Redis集群的数据分片:
- Redis集群引入了哈希槽的概念
- Redis集群有16384个哈希槽(编号0-16383)
- 集群的每个节点负责一部分哈希槽
以3个节点组成的集群为例:
- 节点A包含0到5460号哈希槽
- 节点B包含5461到10922号哈希槽
- 节点C包含10923到16383号哈希槽
Redis集群的主从复制模型
集群中具有A、B、C三个节点,如果节点B失败了,整个集群就会因缺少5461-10922这个范围的槽而不可以用。为每个节点添加一个从节点A1、B1、C1整个集群便有三个Master节点和三个slave节点组成,在节点B失败后,集群选举B1位为的主节点继续服务。当B和B1都失败后,集群将不可用
搭建Redis 群集模式 :
redis的集群一般需要6个节点,3主3从。方便起见,这里所有节点在同一台服务器上模拟:以端口号进行区分:3个主节点端口号:6001/6002/6003,对应的从节点端口号:6004/6005/6006
cd /etc/redis/
mkdir -p redis-cluster/redis600{1..6}
for i in {1..6}
do
cp /opt/redis-5.0.7/redis.conf /etc/redis/redis-cluster/redis600$i
cp /opt/redis-5.0.7/src/redis-cli /opt/redis-5.0.7/src/redis-server /etc/redis/redis-cluster/redis600$i
done
开启群集功能:
其他5个文件夹的配置文件以此类推修改,注意6个端口都要不一样。
cd /etc/redis/redis-cluster/redis6001
vim redis.conf
#bind 127.0.0.1 #69行,注释掉bind 项,默认监听所有网卡
protected-mode no #88行,修改,关闭保护模式
port 6001 #92行,修改,redis监听端口,
daemonize yes #136行,开启守护进程,以独立进程启动
cluster-enabled yes #832行,取消注释,开启群集功能
cluster-config-file nodes-6001.conf #840行,取消注释,群集名称文件设置
cluster-node-timeout 15000 #846行,取消注释群集超时时间设置
appendonly yes #700行,修改,开启AOF
启动redis节点:
分别进入那六个文件夹,执行命令:redis-server redis.conf ,来启动redis节点
cd /etc/redis/redis-cluster/redis6001
redis-server redis.conf
for d in {1..6}
do
cd /etc/redis/redis-cluster/redis600$d
redis-server redis.conf
done
ps -ef | grep redis
#启动集群
redis-cli --cluster create 127.0.0.1:6001 127.0.0.1:6002 127.0.0.1:6003 127.0.0.1:6004 127.0.0.1:6005 127.0.0.1:6006 --cluster-replicas 1
测试群集
redis-cli -p 6001 -c #加-c参数,节点之间就可以互相跳转
127.0.0.1:6001> cluster slots #查看节点的哈希槽编号范围
5798对应上面1范围内的,对应的是6002和6005端口,切换6005端口进行查看