目录
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)节点监控
节点的监控和故障转移跟哨兵的原理几乎一样,集群中的主节点扮演了哨兵的角色,能跟哨兵一样,对其他非主节点进行主观下线,也能因为半数主节点的主观下线而变成客观下线,然后选出新的主节点,实现故障转移。
本文详细介绍了Redis的持久化机制,包括RDB和AOF两种方式的特点及配置;深入解析了主从复制架构,涵盖复制原理、全量复制与部分复制的区别;阐述了哨兵系统如何实现故障自动转移;并探讨了集群的搭建过程与数据分区原理。
1526

被折叠的 条评论
为什么被折叠?



