REDIS高可用之持久化、主从复制、哨兵和集群

本文详细介绍了Redis的持久化机制,包括RDB和AOF两种方式的特点及配置;深入解析了主从复制架构,涵盖复制原理、全量复制与部分复制的区别;阐述了哨兵系统如何实现故障自动转移;并探讨了集群的搭建过程与数据分区原理。

目录

Redis简介

Redis持久化

1、RDB持久化方式

2、AOF持久化方式

3、RDB和AOF优缺点

4、持久化中的阻塞

Redis主从复制

1、主从复制主要作用

2、主从复制架构

3、主从复制配置

4、主从复制原理

5、全量复制和部分复制

6、主从复制问题

Redis哨兵(Redis Sentinel)

1、哨兵主要作用

2、哨兵架构

3、基本原理

4、哨兵架构重要配置

Redis集群

1、集群作用

2、集群搭建过程

3、集群基本原理


Redis简介

Redis是一个key-value存储系统,可基于内存存储,亦可以持久化,常用来做缓存服务器,其value的数据类型包括五种:字符串(String)、散列(Hash)、列表(List)、集合(Set)、有序集合(ZSet)。

Redis作为一个高可用服务,依赖于其几大特性:

持久化:主要解决单机redis环境下,数据备份的问题;

主从复制:可以实现负载均衡、故障恢复以及读写分离;

哨兵:自动发现故障,并进行故障恢复;

集群:解决单机redis内存限制,提高服务能力;

Redis持久化

Redis持久化有两种方式,RDB(Redis DataBase)和AOF(AppendOnly File),RDB的方式通过定期将内存数据备份到磁盘文件上实现持久化,AOF则将发生在redis上的写命令,同步写到磁盘文件中,实时性更高。

1、RDB持久化方式

RDB持久化会在redis指定目录生成一个.rdb文件(默认是redis根目录下的dump.rdb,可以通过配置修改),该文件是一个二进制文件,保存redis内存中当前所有数据,每次RDB持久化都会写一个新的rdb文件,并覆盖旧的rdb文件。

触发RDB持久化的命令有两个:save和bgsave;其中save命令的执行会阻塞redis进程,直到RDB文件生成完成,也就是说整个持久化期间,redis失去了提供服务的能力,一般线上是不能接受的;bgsave命令等于backgroundsave,意指后台save,执行该命令时redis会创建一个子进程(创建子进程也会有短暂的阻塞,大概毫秒级别,时间由redis内存数据大小决定),然后由子进程负责将内存数据持久化到RDB文件中,而主进程照常提供服务。

RDB持久化可以手动触发也可以自动触发

手动触发:通过客户端执行命令bgsave,完成当前redis内存数据的持久化;

自动触发:是在redis部署或启动时,在配置文件中或启动命令中配置相应的自动持久化参数,其参数格式为:save m n,意指m秒内如果发生了n条数据修改,则触发bgsave。

save m n自动触发原理:

redis中有一个周期性函数,定期扫描(默认100ms)redis中需要处理的任务,当redis配置了save m n后,会记录上一次持久化时间lastsave以及上次持久化到现在修改的记录条数,当满足配置条件时,则执行新的一轮bgsave操作。

redis在启动时,会自动加载rdb文件(如果开启了AOF持久化,优先加载aof文件),恢复数据。

RDB持久化下redis.conf配置文件:

save m n : rdb持久化触发条件,如果不配置,则表示不自动持久化;

stop-writes-on-bgsave-error yes:当bgsave出现错误时,是否需要停止redis的写命令操作,设置为yes时,如果出现bgsave错误,则redis服务写不可用,谨慎配置;

rdbcompression yes:是否开启rdb文件压缩;

rdbchecksum yes:是否开启rdb文件校验,有利于数据损坏时的发现,如果设置为no,可以提升写文件和读文件的性能;

dbfilename dump.rdb:rdb文件名;

dir ./:rdb文件和aof文件目录

2、AOF持久化方式

AOF持久化的方式有点类似mysql的binlog,每次发生redis的写操作,都会将命令追加到aof文件中,redis服务启动时会自动加载aof文件,通过aof中记录的写命令还原redis数据。

该持久化开启方式是在redis.conf配置文件中添加appendonly yes;

AOF持久化方式下,发生在redis服务中的写命令,都会同步到缓冲区,然后从缓冲区写到aof文件中,从缓冲区写到aof文件根据不同策略有不同表现,具体分三种,对应了redis.conf文件中的三种配置方式:

1)appendfsync always

该策略下,每次redis的写操作,都会立即写到aof文件中,磁盘IO容易出现瓶颈;

2)appendfsync no

该策略下,redis只负责把写命令同步到缓冲区,不负责写到文件,由操作系统自动写文件,操作系统对缓冲区的操作大概30秒一次,时间间隔较长,服务故障时,容易丢失较多的数据;

3)appendfsync everysec

该策略,算是上述两种策略的折中方案,由redis中一个单独的线程,定时每秒从缓冲区写到文件中;

AOF持久化的是写命令,我们考虑一种场景,对同一个key,执行多次写操作:

set key1 value1;

set key1 value2;

set key1 value3;

那么,aof文件中就记录了三次,这样文件中就多了很多失效和重复的命令,不仅造成aof文件的过于臃肿,而且恢复数据时间也会长很多,所以aof文件需要精简,而redis实现精简的方式就是定期重写aof文件,重写的规则是将当前redis内存中的数据转化为写命令,把这些写命令写到新的aof文件中,并替换掉旧的文件,所以重写并不需要对旧文件进行操作。

重写aof文件可以通过bgrewriteaof命令,这个命令类似bgsave,会fork一个子进程单独处理。

重写规则根据redis.conf中的配置决定,主要依赖两个配置:

auto-aof-rewrite-min-size:执行AOF重写时文件的最小体积,默认64M;

auto-aof-rewrite-percentage:执行AOF重写时,当前AOF文件大小(aof_current_size)和上一次重写时AOF文件大小(aof_base_size)的比值;

只有auto-aof-rewrite-min-size和auto-aof-rewrite-percentage同时满足时才会触发bgrewriteaof

AOF常用配置:

appendonly yes : 是否开启aof

appendfilename appendonly.aof : aof文件名

dir ./ : rdb或aof文件目录

appendfsync everysec : fsync持久化策略

no-appendfsync-on-rewrite no : aof重写期间是否禁止fsync

auto-aof-rewrite-percentage 100 : 文件重写触发条件之一

auto-aof-rewrite-min-size 64mb : 文件重写触发条件之一

aof-reload-truncated yes : 如果aof文件结尾损坏,redis启动时是否加载aof文件

3、RDB和AOF优缺点

RDB文件紧凑,体积小,网络传输快,适合全量复制,恢复数据也很快,但是实时性不高,容易丢失数据;

AOF支持秒级持久化,实时性高,数据完整性更高,但是文件大,恢复速度慢。

4、持久化中的阻塞

fork阻塞:cpu阻塞

无论是bgsave,还是bgrewriteaof,都会fork子进程,创建子进程的过程会阻塞redis,一般如果redis内存在10g,大概百毫秒级别的阻塞,内存越大,创建子进程耗时越长,阻塞时间也会越长;

aof追加阻塞:硬盘阻塞

aof根据策略everysec,每秒将缓存数据写入硬盘,但是如果硬盘负载过高,1秒内数据无法写完,redis主进程不可能无限累加,他会每次aof时判定上一次sync的成功时间,如果距离上次不足2秒,就继续保持每秒sync,如果超过了2秒,redis进程会阻塞,直到sync同步完成

Redis主从复制

1、主从复制主要作用

数据冗余,实现数据热备;

故障恢复,当主节点出现故障,可以由从节点提供服务;

负载均衡,读写分离,主节点提供写,从节点提供读服务,读多时,可以多加几个从节点,提高读并发;

高可用基石,为哨兵和集群提供基础;

2、主从复制架构

主从复制架构中,包含一个主节点,和一个到多个从节点:

3、主从复制配置

配置从节点不需要操作主节点,所有的redis节点启动时默认都是主节点,在主从配置中,只需要将某个redis节点指定为另一个节点的从节点,就能建立主从关系,一个主节点可以有多个从节点,但是一个从节点只能有一个主节点。

可以通过以下三种方式,将一个redis节点变为另一个的从节点:

更改配置文件:

    slaveof [masterip] [masterport]

启动时加入命令:

    redis-server启动命令后加 –slaveof [masterip] [masterport]

客户端命令:

    客户端直接执行命令:slaveof [masterip] [masterport]

如果想解除主从关系,直接在从节点上执行命令slaveof no one,断开后,从节点再次变为主节点,但是不会删除原有的数据,只是不再被同步数据;

4、主从复制原理

1)通过slaveof命令建立主从关系;

2)建立socket连接

从节点每秒调用一次复制定时函数replicationCron(),如果发现有主节点可用,则尝试连接,如果连接成功,从节点会为当前socket连接创建一个单独的事务处理器,用来复制rpd,同步命令等;主节点将从节点视为一个客户端,接收其命令请求;

从节点发送ping命令,用来判定当前socket是否可用,如果返回超时或其他异常,会断开重连;

身份验证,如果从节点配置了masterauth选项,则从节点需要向主节点发送auth命令进行身份验证,验证不通过会断开重连;

3)数据同步阶段

连接建立后,开始数据同步,以从节点发送psync命令开始,根据状态不同,进行全量数据复制或部分数据复制;

4)命令传播阶段

数据同步后,所有主节点的写命令传播给从节点,从节点根据写命令保持节点的数据一致,此阶段除了写命令同步,还有心跳检测;

 

 

5、全量复制和部分复制

全量复制用于初次复制和无法部分复制的场景;

部分复制用于临时中断后恢复中断期间的数据,如果中断时间过长,主节点缓存的中断数据过多而丢失,需要全量复制;

全量复制过程:

1)主节点执行bgsave,生成rdb文件,并使用缓冲区记录此刻开始进来的新的写命令;

2)主节点生成完的rdb文件后发送给从节点,从节点清除自己的旧数据,加载主节点的rdb文件;

3)主节点将缓冲区的写命令同步给从节点,从节点执行完保持数据一致;

4)如果从节点开启了aof,会执行rewriteaof,保证当前aof的文件数据一致性;

由于全量复制开销比价大,所以有些情况会用部分复制,部分复制依赖几个条件:

1)复制偏移量,主节点和从节点分别维护传递的数据字节数,两者记录的数据偏移量一样表示数据当前处于一致,如果不一致,说明从节点丢失部分数据,比如,主节点offset1000,从节点500,那么从节点丢失了501-1000的数据,这部分数据可以通过部分复制完成,丢失的数据位于主节点的复制积压缓冲区,也就是主节点同步数据的备份;

2)复制积压缓冲区,是主节点维护的一个fifo队列,大小默认1MB,所有最近同步给从节点的写命令,会备份到这个缓冲区,如果需要恢复丢失的数据,可以从缓冲区再次同步丢失的命令,但是因为缓冲区有大小限制,如果丢失的数据在缓冲区也没有了,那么就需要进行全量复制了;

3)服务器运行ID,每个redis服务启动时都会生成一个随机ID,主从初次复制同步时,主节点会将自己的ID发送给从节点,从节点保存主节点ID,当从节点断线后重连,会将此ID发送给主节点,那么主节点就知道该从节点之前同步过自己,且中断过,那么,主节点会为尝试为从节点进行部分复制,如果ID对不上,说明从节点之前的主节点不是现在的主节点,那么需要全部复制。

 

 

6、主从复制问题

1)延迟和不一致问题,主从复制是异步过程,在读写分离的场景中,主节点写的数据,并不能保证在从节点能立马读到;

2)数据过期问题,在单机redis中存在惰性删除(服务器不主动删除,只有客户端读时,才会判断是否过期需要删除)和定期删除(服务器定期检测过期数据并删除)两种删除策略,但是主从架构中,为了保证数据一致,从服务器不会主动删除数据,而是由主节点发起从节点的数据删除,当删除不及时,从节点读取的数据可能已经过期,在redis3.2版本后,数据过期不会返回了。

3)故障切换问题,在没有使用哨兵情况下,发生故障,只能手动切换。

Redis哨兵(Redis Sentinel)

普通的主从架构,当master服务器发生故障时,需要人为干预,进行故障切换,而哨兵的存在,则可以避免人为操作,自动化实现故障的发现以及故障转移。

1、哨兵主要作用

监控:哨兵会不断检查主节点和从节点是否工作异常,多个哨兵之间也会互相监控;

自动转移故障:主节点出现故障时,会自动将其中一个从节点升级为主节点,并将其他从节点的主节点信息进行更新;

配置提供者:客户端(Redis API)可以直接通过连接哨兵来获取redis主节点信息;

通知:哨兵可以将故障转移的结果通知到客户端;

 

2、哨兵架构

哨兵节点:由一个或多个哨兵节点组成,哨兵节点也是redis实例,不过不存数据;

数据节点:存储数据的主从redis节点

3、基本原理

1)哨兵节点的配置文件中配置了主节点的信息;

2)哨兵节点打开到主节点的socket,并维护三个定时任务,其一,通过向主节点发送info命令获取最新的主从架构信息;其二,通过发布订阅获取其他哨兵节点的信息;其三,向其他节点发送ping命令,判断是否下线;

3)哨兵节点定时对其他节点(主节点、从节点和其他哨兵节点)进行心跳检测,如果发现节点超时没响应,就会主观认为该节点已经下线,这种主观判定叫做主观下线;

4)如果一个哨兵节点对一个主节点进行了主观下线,它会通过sentinel is-master-down-by-addr命令询问其他哨兵节点该主节点状态,如果判断该主节点下线的哨兵数量达到配置的最低数量,则会对该主节点进行客观下线(只有主节点才有客观下线,从节点和哨兵节点故障只有主观下线);

5)当主节点被客观下线后,哨兵节点会通过选举算法(RAFT算法)选出一个哨兵leader,由这个哨兵leader对主节点故障进行转移;

6)被选出的哨兵leader开始对主节点故障转移,主要操作是在所有从节点中选出一个节点作为新的主节点,第一步,选择一个从节点作为新主节点,原则是,首先过滤掉不健康(通讯有故障)的从节点,然后根据配置的优先级(slave-priority)选择节点,如果优先级无法区分,则选择复制偏移量最大(即数据最全)的节点,如果仍然不能区分,选择id最小的节点;第二步,更新主从状态,被选中的从节点执行slaveof no one命令成为主节点,并对其他从节点执行slaveof命令连接到新主节点;第三步,将故障主节点,设置为新主节点的从节点,当主节点重新上线后,变为新主节点的从节点。

4、哨兵架构重要配置

sentinel monitor [mastername] [masterip] [masterport] [quorum]

配置当前节点为哨兵节点,且监控的主节点名称是[mastername],[quorum]表示哨兵节点对主节点客观下线的数量阈值,一般为哨兵数量的一半加1;

sentinel down-after-milliseconds [mastername] [time]

心跳检测无响应主观下线的时间阈值,默认30000ms

Redis集群

 

 

1、集群作用

1)数据分区,解决单机redis内存限制,提供读写性能和并发;

2)高可用,集群支持主从复制和主节点故障转移(与哨兵类似,不同在于,哨兵架构中有单独的哨兵节点进行监控和故障转移,而集群中所有节点都是数据节点,同时每个节点都维护了整个集群中所有节点的信息,并能互相进行监控)

 

2、集群搭建过程

手动执行过程:

1)安装好redis实例,相对于单机redis,配置中主要添加:

cluster-enabled yes 表示使用集群模式启动

cluster-config-file “node-7000.conf” 该配置,指定集群配置文件,每个节点都有一个,用来记录集群信息,由redis节点自动维护,当redis重启时会从该配置中获取集群信息,从而加入集群;

使用redis-server redis.conf 启动该redis节点

此时仅仅只是已集群的方式启动了一个节点,并没有形成真正的集群,也没有建立主从节点;

2)节点握手

假设集群中有6个节点,3主3从,这些节点按步骤1启动后还是彼此独立的,必须通过握手将所有节点加入到一个集群中,通过其中一台节点,依此执行cluster meet [ip] [port]命令,将其他节点都联合起来(这里的ip,只能使用局域网ip,不能使用localhost或127.0.0.1)

3)分配槽

redis集群有16384个数据槽,必须全部分给所有主节点,我们从上述6台节点中选择三个节点将数据槽分配掉,使用命令:cluster addslots,如下:

./reids-cli –h [ip1] –p [port1] cluster addslots {0..5461}

./reids-cli –h [ip2] –p [port2] cluster addslots {5462..10922}

./reids-cli –h [ip3] –p [port3] cluster addslots {10923..16383}

4)最后指定主从关系

集群指定主从关系不用slaveof命令,而使用cluster replicate命令,首先需要通过./redis-cli cluster nodes获取主节点的节点ID,然后使用命令:

./redis-cli –h [ip4] –p [port4] cluster replicate [master node id1]

./redis-cli –h [ip5] –p [port5] cluster replicate [master node id2]

./redis-cli –h [ip6] –p [port6] cluster replicate [master node id3]

这样整个集群就搭建好了。

使用脚本搭建集群:

安装ruby环境,使用redis自带的redis-trib.rb脚本创建

一个redis集群至少需要三主三从,且为了高可用,都需要部署在不同的服务器上。

 

 

3、集群基本原理

1)数据分区

数据分区有顺序分区和哈希分区,哈希分区是将存储key求hash后决定存储分区;

哈希算法包括普通哈希取余、一致性哈希算法和带虚拟节点的一致性哈希算法;

数据分区有两个主要考虑因素:数据分布均匀和增减节点对数据分布的影响;

普通哈希取余:将key的hash值对节点数取余后放到相应的节点上,但是当节点增减时,大量数据需要重新分区;

一致性哈希:对hash算法的最小值和最大值形成一个排列圈,将服务器节点均匀分布在圈上,对key取得的hash值在圈上定位位置,并顺时针找到第一个服务器节点,就是存储的节点,这种情况当节点增减时,虽然不需要大量数据的移动,但是相邻节点的数据需要迁移,导致数据分布不均匀;

带虚拟节点的一致性哈希:redis使用的就是此方案,redis有16384个虚拟节点,将key取hash后的值均匀分配到虚拟节点,再由虚拟节点映射到真实节点,当真实节点增减时,只需要将部分虚拟节点重新映射就可以了。

redis的hash算法使用CRC16

2)节点监控

节点的监控和故障转移跟哨兵的原理几乎一样,集群中的主节点扮演了哨兵的角色,能跟哨兵一样,对其他非主节点进行主观下线,也能因为半数主节点的主观下线而变成客观下线,然后选出新的主节点,实现故障转移。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值