Redis高可用方案(持久化+复制+哨兵+集群)

一、高可用相关概念

高可用:是当一台服务器停止服务后,对于业务及用户毫无影响。 
停止服务的原因可能由于网卡、路由器、机房、CPU负载过高、内存溢出、自然灾害等不可预期的原因导致,在很多时候也称单点问题。

单点问题的2种解决方案
(1)主备方式(简单情景)
这种通常是一台主机、一台或多台备机,在正常情况下主机对外提供服务,并把数据同步到备机,当主机宕机后,备机立刻开始服务。 Redis HA中使用比较多的是keepalived,它使主机备机对外提供同一个虚拟IP,客户端通过虚拟IP进行数据操作,正常期间主机一直对外提供服务,宕机后VIP自动漂移到备机上。优点是对客户端毫无影响,仍然通过VIP操作。 缺点也很明显,在绝大多数时间内备机是一直没使用,被浪费着的。
(2)主从方式(推荐)
这种采取一主多从的办法,主从之间进行数据同步。 当Master宕机后,通过选举算法(Paxos、Raft)从slave中选举出新Master继续对外提供服务,主机恢复后以slave的身份重新加入。 主从另一个目的是进行读写分离,这是当单机读写压力过高的一种通用型解决方案。 其主机的角色只提供写操作或少量的读,把多余读请求通过负载均衡算法分流到单个或多个slave服务器上。
缺点是主机宕机后,Slave虽然被选举成新Master了,但对外提供的IP服务地址却发生变化了,意味着会影响到客户端。 解决这种情况需要一些额外的工作,在当主机地址发生变化后及时通知到客户端,客户端收到新地址后,使用新地址继续发送新请求。
其中,有3种主从拓扑:
a.一主一从:用于主节点故障转移从节点,当主节点的“写”命令并发高且需要持久化,可以只在从节点开启AOF(主节点不需要),这样即保证了数据的安全性,也避免持久化对主节点的影响。
b.一主多从:针对“读”较多的场景,“读”由多个从节点来分担,但节点越多,主节点同步到多节点的次数也越多,影响带宽,也加重主节点的负担。
c.树状主从:一主多从的缺点(主节点推送次数多压力大)可用些方案解决,主节点只推送一次数据到从节点1,再由从节点2推送到11,减轻主节点推送的压力
图片-图片-图片

单点问题的方案选择:
主备(keepalived)方案配置简单、人力成本小,在数据量少、压力小的情况下推荐使用。如果数据量比较大,不希望过多浪费机器,还希望在宕机后,做一些自定义的措施,比如报警、记日志、数据迁移等操作,推荐使用主从方式,因为和主从搭配的一般还有个管理监控中心。

2种Redis的数据同步方式(主备|主从都牵扯到数据同步)
(1)同步方式(数据强一致性):当主机收到客户端写操作后,以同步方式把数据同步到从机上,当从机也成功写入后,主机才返回给客户端成功,也称数据强一致性。 很显然这种方式性能会降低不少,当从机很多时,可以不用每台都同步,主机同步某一台从机后,从机再把数据分发同步到其他从机上,这样提高主机性能分担同步压力。 在redis中是支持这杨配置的,一台master,一台slave,同时这台salve又作为其他slave的master。
(2)异步方式(数据弱一致性):主机接收到写操作后,直接返回成功,然后在后台用异步方式把数据同步到从机上。 这种同步性能比较好,但无法保证数据的完整性,比如在异步同步过程中主机突然宕机了,也称这种方式为数据弱一致性

 

二、Redis实现高可用的4种技术

(1)持久化:最简单的方法,主要作用是数据备份,即将数据存储在硬盘,保证数据不会因进程退出而丢失。
(2)复制:是Redis的基础,哨兵和集群都是在复制基础上实现高可用的。复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。缺陷:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制。
(3)哨兵:在复制的基础上,哨兵实现了自动化的故障恢复。缺陷:写操作无法负载均衡;存储能力受到单机的限制。
(4)集群:通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题,实现了较为完善的高可用方案。

 优点缺点
持久化数据备份在硬盘 
复制

数据的多机备份;

读操作的负载均衡;

简单的故障恢复;

存储能力受到单机的限制;

写操作无法负载均衡;

故障恢复无法自动化;

哨兵自动化的故障恢复

存储能力受到单机的限制;

写操作无法负载均衡;

集群

存储能力受到单机限制的问题;

写操作无法负载均衡;

 


三、持久化

1、持久化的功能
Redis是内存数据库,数据都是存储在内存中,为了避免进程退出导致数据的永久丢失,需要定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复。除此之外,为了进行灾难备份,可以将持久化文件拷贝到一个远程位置。

2、持久化的方式及优缺点
分为RDB持久化(快照持久化)和AOF持久化(日志持久化)。
(1)RDB持久化(快照持久化):将当前数据保存到硬盘。
--->优点:RDB文件紧凑,体积小,网络传输快,适合全量复制;恢复速度比AOF快很多。当然,与AOF相比,RDB最重要的优点之一是对性能的影响相对较小。
--->缺点:RDB文件的致命缺点在于其数据快照的持久化方式决定了必然做不到实时持久化,而在数据越来越重要的今天,数据的大量丢失很多时候是无法接受的,因此AOF持久化成为主流。此外,RDB文件需要满足特定格式,兼容性差(如老版本的Redis不兼容新版本的RDB文件)。
(2)AOF持久化(日志持久化):将每次执行的写命令保存到硬盘(类似于MySQL的binlog)
--->优点在于支持秒级持久化、兼容性好。由于AOF持久化的实时性更好,即当进程意外退出时丢失的数据更少,因此AOF是目前主流的持久化方式。
--->缺点是文件大、恢复速度慢、对性能影响大。

【持久化方式的取舍】
(1)如果Redis中的数据完全丢弃也没有关系(如Redis完全用作DB层数据的cache),那么无论是单机,还是主从架构,都可以不进行任何持久化。
(2)在单机环境下(对于个人开发者,这种情况可能比较常见),如果可以接受十几分钟或更多的数据丢失,选择RDB对Redis的性能更加有利;如果只能接受秒级别的数据丢失,应该选择AOF。
(3)但在多数情况下,我们都会配置主从环境,slave的存在既可以实现数据的热备,也可以进行读写分离分担Redis读请求,以及在master宕掉后继续提供服务。
在这种情况下,一种可行的做法是:
master:完全关闭持久化(包括RDB和AOF),这样可以让master的性能达到最好
slave:关闭RDB,开启AOF(如果对数据安全要求不高,开启RDB关闭AOF也可以),并定时对持久化文件进行备份(如备份到其他文件夹,并标记好备份的时间);然后关闭AOF的自动重写,然后添加定时任务,在每天Redis闲时(如凌晨12点)调用bgrewriteaof。
(4)异地灾备
:上述讨论的几种持久化策略,针对的都是一般的系统故障,如进程异常退出、宕机、断电等,这些故障不会损坏硬盘。但是对于一些可能导致硬盘损坏的灾难情况,如火灾地震,就需要进行异地灾备。例如对于单机的情形,可以定时将RDB文件或重写后的AOF文件,通过scp拷贝到远程机器,如阿里云、AWS等;对于主从的情形,可以定时在master上执行bgsave,然后将RDB文件拷贝到远程机器,或者在slave上执行bgrewriteaof重写AOF文件后,将AOF文件拷贝到远程机器上。一般来说,由于RDB文件文件小、恢复快,因此灾难恢复常用RDB文件;异地备份的频率根据数据安全性的需要及其他条件来确定,但最好不要低于一天一次。

为什么开启了主从复制,可以实现数据的热备份,还需要设置持久化呢?
因为在一些特殊情况下,主从复制仍然不足以保证数据的安全。
如下是2个例子:
(1)master和slave进程同时停止:考虑这样一种场景,如果master和slave在同一栋大楼或同一个机房,则一次停电事故就可能导致master和slave机器同时关机,Redis进程停止;如果没有持久化,则面临的是数据的完全丢失。
(2)master误重启:考虑这样一种场景,master服务因为故障宕掉了,如果系统中有自动拉起机制(即检测到服务停止后重启该服务)将master自动重启,由于没有持久化文件,那么master重启后数据是空的,slave同步数据也变成了空的;如果master和slave都没有持久化,同样会面临数据的完全丢失。需要注意的是,即便是使用了哨兵进行自动的主从切换,也有可能在哨兵轮询到master之前,便被自动拉起机制重启了。因此,应尽量避免“自动拉起机制”和“不做持久化”同时出现。

2种阻塞及其解法?
(1)fork阻塞:CPU的阻塞
在Redis的实践中,众多因素限制了Redis单机的内存不能过大,例如:
a.当面对请求的暴增,需要从库扩容时,Redis内存过大会导致扩容时间太长;
b.当主机宕机时,切换主机后需要挂载从库,Redis内存过大导致挂载速度过慢;
c.持久化过程中的fork操作,下面详细说明。
首先说明一下fork操作:
父进程通过fork操作可以创建子进程;子进程创建后,父子进程共享代码段,不共享进程的数据空间,但是子进程会获得父进程的数据空间的副本。在操作系统fork的实际实现中,基本都采用了写时复制技术,即在父/子进程试图修改数据空间之前,父子进程实际上共享数据空间;但是当父/子进程的任何一个试图修改数据空间时,操作系统会为修改的那一部分(内存的一页)制作一个副本。虽然fork时,子进程不会复制父进程的数据空间,但是会复制内存页表(页表相当于内存的索引、目录);父进程的数据空间越大,内存页表越大,fork时复制耗时也会越多。

 在Redis中,无论是RDB持久化的bgsave,还是AOF重写的bgrewriteaof,都需要fork出子进程来进行操作。如果Redis内存过大,会导致fork操作时复制内存页表耗时过多;而Redis主进程在进行fork时,是完全阻塞的,也就意味着无法响应客户端的请求,会造成请求延迟过大。

对于不同的硬件、不同的操作系统,fork操作的耗时会有所差别,一般来说,如果Redis单机内存达到了10GB,fork时耗时可能会达到百毫秒级别(如果使用Xen虚拟机,这个耗时可能达到秒级别)。因此,一般来说Redis单机内存一般要限制在10GB以内;不过这个数据并不是绝对的,可以通过观察线上环境fork的耗时来进行调整。观察的方法如下:执行命令info stats,查看latest_fork_usec的值,单位为微秒。

为了减轻fork操作带来的阻塞问题,除了控制Redis单机内存的大小以外,还可以适度放宽AOF重写的触发条件、选用物理机或高效支持fork操作的虚拟化技术等,例如使用Vmware或KVM虚拟机,不要使用Xen虚拟机。


(2)AOF追加阻塞:硬盘的阻塞
在AOF中,如果AOF缓冲区的文件同步策略为everysec,则:在主线程中,命令写入aof_buf后调用系统write操作,write完成后主线程返回;fsync同步文件操作由专门的文件同步线程每秒调用一次。

这种做法的问题在于,如果硬盘负载过高,那么fsync操作可能会超过1s;如果Redis主线程持续高速向aof_buf写入命令,硬盘的负载可能会越来越大,IO资源消耗更快;如果此时Redis进程异常退出,丢失的数据也会越来越多,可能远超过1s。

为此,Redis的处理策略是这样的:主线程每次进行AOF会对比上次fsync成功的时间;如果距上次不到2s,主线程直接返回;如果超过2s,则主线程阻塞直到fsync同步完成。因此,如果系统硬盘负载过大导致fsync速度太慢,会导致Redis主线程的阻塞;此外,使用everysec配置,AOF最多可能丢失2s的数据,而不是1s。

AOF追加阻塞问题定位的方法:
a.监控info Persistence中的aof_delayed_fsync:当AOF追加阻塞发生时(即主线程等待fsync而阻塞),该指标累加。
b.AOF阻塞时的Redis日志:Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.
c.如果AOF追加阻塞频繁发生,说明系统的硬盘负载太大;可以考虑更换IO速度更快的硬盘,或者通过IO监控分析工具对系统的IO负载进行分析,如iostat(系统级io)、iotop(io版的top)、pidstat等。

info命令与持久化


四、哨兵机制

使用主从机制,主节点出现了问题需通过人工干预的方式把从节点设为主节点,并通知应用程序更新主节点地址,该方式繁琐笨重,且主节点的读写能力十分有限。引出“哨兵”。
(1)哨兵的作用:监控Redis系统的运行状况
(2)哨兵的4个主要功能(面试考)
a.集群监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常。
b.消息通知(Notification): 当被监控的某个 Redis出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知。
c.自动故障迁移(Automatic failover): 如果master node挂掉了,会自动转移到slave node上。当主数据库出现故障时自动将从数据库转换为主数据库。
d.配置中心:如果故障转移发生了,通知client客户端新的master地址。
(3)哨兵的原理Redis哨兵的三个定时任务实例来判定一个Redis节点故障不可达(面试考)
Job1:每隔10秒每个哨兵节点会向主节点和从节点发送"info replication" 命令来获取最新的拓扑结构
Job2:每隔2秒每个哨兵节点会向Redis节点的_sentinel_:hello频道发送自己对主节点是否故障的判断以及自身的节点信息,并且其他的哨兵节点也会订阅这个频道来了解其他哨兵节点的信息以及对主节点的判断
Job3:每隔1秒每个哨兵会向主节点、从节点、其他的哨兵节点发送一个 “ping” 命令来做心跳检测

Job1:每10s每个哨兵节点,向主+从节点,发"info replication"命令,获取最新拓扑结构

Job2:每2s每个哨兵节点,向主+从节点的"_sentinel_:hello"频道,

(a.发自己对主节点是否故障的判断以及自身的节点信息;b.订阅这个频道来了解其他哨兵节点的信息以及对主节点的判断)

Job3:每1s每个哨兵节点,向主+从+其它哨兵节点,发"ping"命令来做心跳检测

【主观下线与客观下线】:如果在定时Job3检测不到节点的心跳,会判断为“主观下线”。如果该节点是主节点那么还会通知到其他的哨兵对该主节点进行心跳检测,这时主观下线的票数超过了<quorum>数时,那么这个主节点确实就可能是故障不可达了,这时就由原来的主观下线变为了“客观下线”。
【故障转移和Leader选举】:如果主节点被判定为客观下线之后,就要选取一个哨兵节点来完成后面的故障转移工作,选举出一个leader,这里面采用的选举算法为Raft。选举出来的哨兵leader就要来完成故障转移工作,也就是在从节点中选出一个节点来当新的主节点,这部分的具体流程可参考引用 https://blog.csdn.net/nuomizhende45/article/details/82831966《深入理解Redis哨兵搭建及原理》


五、分布式与集群

(1)Redis集群:至少部署两台Redis服务器构成一个小的集群。
(2)集群的2个目的:高可用性与读写分离。
高可用性:在主机挂掉后,自动故障转移,使前端服务对用户无影响。
读写分离:将主机读压力分流到从机上。

(3)Redis集群设计包括2部分:哈希Slot和节点主从
(4)Redis集群架构对比及选型:https://blog.csdn.net/u013473512/article/details/79044683

转载:

Redis高可用详解:持久化技术及方案选择

Redis高可用策略与集群方案

Redis高可用方案-哨兵与集群

Redis面试题及分布式集群

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值