当前位置: 首页 > news >正文

Redis实战和核心原理详解(8)使用快照RDB和AOF将Redis数据持久化到硬盘中

一、前言

我们知道Redis是一款内存服务器,就算我们对自己的服务器足够的信任,不会出现任何软件或者硬件的故障,但也会有可能出现突然断电等情况,造成Redis服务器中的数据失效。因此,我们需要向传统的关系型数据库一样对数据进行备份,将Redis在内存中的数据持久化到硬盘等非易失性介质中,来保证数据的可靠性。

将Redis内存服务器中的数据持久化到硬盘等介质中的一个好处就是,使得我们的服务器在重启之后还可以重用以前的数据,或者是为了防止系统出现故障而将数据备份到一个远程的位置。

还有一些场景,例如:

对于一些需要进行大量计算而得到的数据,放置在Redis服务器,我们就有必要对其进行数据的持久化,如果需要对数据进行恢复的时候,我们就不需进行重新的计算,只需要简单的将这台机器上的数据复制到另一台需要恢复的Redis服务器就可以了。

Redis中数据存储模式有2种:

  • cache-only,即只做为“缓存”服务,不持久数据,数据在服务终止后将消失,此模式下也将不存在“数据恢复”的手段,是一种安全性低/效率高/容易扩展的方式;

  • persistence,即为内存中的数据持久备份到磁盘文件,在服务重启后可以恢复,此模式下数据相对安全。

对于persistence持久化存储,Redis提供了两种持久化方法:

  • Redis DataBase(简称RDB),快照(Snapshotting) ;
  • Append-only file (简称AOF),只追加文件(append-only-file) ;

除了这两种方法,Redis在早起的版本还存在虚拟内存的方法,现在已经被废弃。

1.1、名词简介

(1)快照(RDB):就是我们俗称的备份,他可以在定期内对数据进行备份,将Redis服务器中的数据持久化到硬盘中;

文件格式是:dump.rdb

RDB持久化机制是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,在替换之前的文件,用二进制压缩存储。
在这里插入图片描述

(2)只追加文件(AOF):他会在执行写命令的时候,将执行的写命令复制到硬盘里面,后期恢复的时候,只需要重新执行一下这个写命令就可以了。类似于我们的MySQL数据库在进行主从复制的时候,使用的是binlog二进制文件,同样的是执行一遍写命令;AOF会记录每一个写、删除操作,查询操作不会被记录,以文件的形式记录,可以打开文件看到详细的操作记录。

文件格式是:appendonly.aof

在这里插入图片描述

1.2、快照RDB持久化通用的配置:

save 60 1000  #60秒时间内有1000次写入操作的时候执行快照的创建
stop-writes-on-bgsave-error no  #创建快照失败的时候是否仍然继续执行写命令
rdbcompression yes  #是否对快照文件进行压缩
dbfilename dump.rdb   #如何命名硬盘上的快照文件
dir ./  #快照所保存的位置

1.3、AOP持久化配置:

appendonly no  #是否使用AOF持久化
appendfsync everysec  #多久执行一次将写入内容同步到硬盘上
no-appendfsync-on-rewrite no #对AOF进行压缩的时候能否执行同步操作
auto-aof-rewrite-percentage 100  #多久执行一次AOF压缩
auto-aof-rewrite-min-size 64mb  #多久执行一次AOF压缩
dir ./ #AOF所保存的位置

需要注意的是:这两种持久化的方式既可以单独的使用,也可以同时使用,具体选择哪种方式需要根据具体的情况进行选择。

二、RDB快照持久化

快照就是我们所说的备份。用户可以将Redis内存中的数据在某一个时间点进行备份,在创建快照之后,用户可以对快照进行备份。通常情况下,为了防止单台服务器出现故障造成所有数据的丢失,我们还可以将快照复制到其他服务器,创建具有相同数据的数据副本,这样的话,数据恢复的时候或者服务器重启的时候就可以使用这些快照信息进行数据的恢复,也可以防止单台服务器出现故障的时候造成数据的丢失。

但是,没我们还需要注意的是,创建快照的方式,并不能完全保证我们的数据不丢失,这个大家可以很好的理解,因为快照的创建时定时的,并不是每一次更新操作都会创建一个快照的。系统发生崩溃的时候,用户将丢失最近一次生成快照之后更改的所有数据。因此,快照持久化的方式只适合于数据不经常修改或者丢失部分数据影响不大的场景。

2.1、创建快照的方式:

(1)客户端通过向Redis发送BGSAVE 命令来创建快照。

使用BGSAVE的时候,Redis会调用fork来创建一个子进程,然后子进程负责将快照写到硬盘中,而父进程则继续处理命令请求。

使用场景:

如果用户使用了save设置,例如:save 60 1000 ,那么从Redis最近一次创建快照之后开始计算,当“60秒之内有1000次写入操作”这个条件满足的时候,Redis就会自动触发BGSAVE命令。

如果用户使用了多个save设置,那么当任意一个save配置满足条件的时候,Redis都会触发一次BGSAVE命令。

(2)客户端通过向Redis发送SAVE 命令来创建快照。

接收到SAVE命令的Redis服务器在快照创建完毕之前将不再响应任何其他命令的请求。SAVE命令并不常用,我们通常只在没有足够的内存去执行BGSAVE命令的时候才会使用SAVE命令,或者即使等待持久化操作执行完毕也无所谓的情况下,才会使用这个命令;

使用场景:

当Redis通过SHUTDOWN命令接收到关闭服务器的请求时,或者接收到标准的TERM信号时,会执行一次SAVE命令,阻塞所有的客户端,不再执行客户端发送的任何命令,并且在执行完SAVE命令之后关闭服务器。

2.2、命令的含义:

RDB持久化会对redis中的数据进行周期性的持久化,生成一份快照文件,存放在配置文件声明的目录下面的dump.rdb文件。在redis配置文件中可以通过配置dir属性来指定持久化文件存放目录。默认情况下RDB持久化是打开的,可以在配置文件中找到如下内容:

save 900 1
save 300 10
save 60 10000

上述命令指的是如果900秒内有1个key发生了变化,生成一份快照文件,如果再300秒内有10个key发生了改变,生成一份快照文件,如果在60秒内有10000个key发生了改变,生成一份快照文件。

save可以设置多个,就是多个snapshotting检查点,每到一个检查点,就会去检查一下,是否有指定的key数量发生变化,如果有就生成一个新的dump.rdb文件。

也可以通过save或者bgsave命令同步或异步指定rdb快照生成。

save命令的注意事项:

save 900 1

这条命令指的是两个数字同时生效的时候,才会执行具体的RDB,并不是到了900秒或者有一条数据已经发生了改变就进行RDB了,两个条件是同时满足的!官网的解释说明了这个问题,

在这里插入图片描述

2.3、RDB持久化的工作流程:

在这里插入图片描述

具体流程如下:

  • Redis根据配置自己尝试生成RDB快照文件;
  • fork一个子进程出来;
  • 子进程尝试将数据写到临时的RDB快照文件中;
  • 完成RDB快照文件的生成之后,就替换之前旧的快照文件;

dump.rdb 每次生成一个快照,都会覆盖之前的旧文件。

2.4、使用RDB快照持久化注意事项:

我们在使用快照的方式来保存数据的时候,如果Redis服务器中的数据量比较小的话,例如只有几个GB的时候。Redis会创建子进程并将数据保存到硬盘里边,生成快照所需的时间比读取数据所需要的时间还要短。

但是,随着数据的增大,Redis占用的内存越来越大的时候,BGSAVE在创建子进程的时候消耗的时间也会越来越多,如果Redis服务器所剩下的内存不多的时候,这行BGSAVE命令会使得系统长时间地停顿,还有可能导致服务器无法使用。

各虚拟机类别,创建子线程所耗时间:
这里写图片描述
因此,为了防止Redis因为创建子进程的时候出现停顿,我们可以考虑关闭自动保存,转而通过手动的方式发送BGSAVE或者SAVE来进行持久化,

手动的方式发送BGSAVE也会出现停顿的现象,但是我们可以控制发送该命令的时间来控制出现停顿的时候不影响具体的业务请求。

另外,值得注意的是,在使用SAVE命令的时候,虽然会一直阻塞Redis直到快照生成完毕,但是其不需要创建子进程,所以不会向BGSAVE一样,因为创建子进程而导致Redis停顿。也正因为如此,SAVE创建快照的速度要比BGSAVE创建快照的速度更快一些。

创建快照的时候,我们可以在业务请求,比较少的时候,比如凌晨三、四点,通过手写脚本的方式,定时执行。

三、AOF持久化

AOF持久化会将被执行的写命令写到AOF文件的末尾,以此来记录数据发生的变化。这样,我们在恢复数据的时候,只需要从头到尾的执行一下AOF文件即可恢复数据。

3.1、打开AOF持久化选项

我们可以通过使用如下命令打开AOF:

appendonly yes

我们,通过如下命令来配置AOF文件的同步频率:

appendfsync everysec/always/no

3.2、appendfsync同步频率的区别

appendfsync同步频率的区别如下图:

这里写图片描述

(1)always的方式固然可以对没一条数据进行很好的保存,但是这种同步策略需要对硬盘进行大量的写操作,所以Redis处理命令的速度会受到硬盘性能的限制。

普通的硬盘每秒钟只能处理大约200个写命令,使用固态硬盘SSD每秒可以处理几万个写命令,但是每次只写一个命令,这种只能怪不断地写入很少量的数据的做法有可能引发严重的写入放大问题,这种情况下降严重影响固态硬盘的使用寿命。

(2)everysec的方式,Redis以每秒一次的频率大队AOF文件进行同步。这样的话既可以兼顾数据安全也可以兼顾写入性能。

Redis以每秒同步一次AOF文件的性能和不使用任何持久化特性时的性能相差无几,使用每秒更新一次 的方式,可以保证,即使出现故障,丢失的数据也在一秒之内产生的数据。

(3)no的方式,Redis将不对AOF文件执行任何显示的同步操作,而是由操作系统来决定应该何时对AOF文件进行同步。

这个命令一般不会对Redis的性能造成多大的影响,但是当系统出现故障的时候使用这种选项的Redis服务器丢失不定数量的数据。

另外,当用户的硬盘处理写入操作的速度不够快的话,那么缓冲区被等待写入硬盘的数据填满时,Redis的写入操作将被阻塞,并导致Redis处理命令请求的速度变慢,因为这个原因,一般不推荐使用这个选项。

3.3、重写/压缩AOF文件

随着数据量的增大,AOF的文件可能会很大,这样在每次进行数据恢复的时候就会进行很长的时间,为了解决日益增大的AOF文件,用户可以向Redis发送BGREWRITEAOF 命令,这个命令会通过移除AOF文件中的冗余命令来重写AOF文件,是AOF文件的体检变得尽可能的小。

BGREWRITEAOF的工作原理和BGSAVE的原理很像:Redis会创建一个子进程,然后由子进程负责对AOF文件的重写操作。

因为AOF文件重写的时候会创建子进程,所以快照持久化因为创建子进程而导致的性能和内存占用问题同样会出现在AOF文件重写的 时候。

3.4、触发重写/压缩AOF文件条件设定

AOF通过设置auto-aof-rewrite-percentageauto-aof-rewrite-min-size 选项来自动执行BGREWRITEAOF。

其具体含义,通过实例可以看出,如下配置:

auto-aof-rewrite-percentage 100 
auto-aof-rewrite-min-size 64mb

表示当前AOF的文件体积大于64MB,并且AOF文件的体积比上一次重写之后的体积变大了至少一倍(100%)的时候,Redis将执行重写BGREWRITEAOF命令。

如果AOF重写执行的过于频繁的话,可以将auto-aof-rewrite-percentage 选项的值设置为100以上,这种最偶发就可以让Redis在AOF文件的体积变得更大之后才执行重写操作,不过,这也使得在进行数据恢复的时候执行的时间变得更加长一些。

3.5、AOF工作流程

在这里插入图片描述

四、验证RDB快照文件和AOF文件

无论使用哪种方式进行持久化,我们在进行恢复数据的时候,Redis提供了两个命令行程序:

redis-check-aof
redis-check-dump

他们可以再系统发生故障的时候,检查快照和AOF文件的状态,并对有需要的情况对文件进行修复。

如果用户在运行redis-check-aof命令的时候,指定了--fix 参数,那么程序将对AOF文件进行修复。

程序修复AOF文件的方法很简单:他会扫描给定的AOF文件,寻找不正确或者不完整的命令,当发现第一个出现错误命令的时候,程序会删除出错命令以及出错命令之后的所有命令,只保留那些位于出错命令之前的正确命令。大部分情况,被删除的都是AOF文件末尾的不完整的写命令。

五、RDB和AOF的注意事项

  • 这两种持久化的方式既可以单独的使用,也可以同时使用,具体选择哪种方式需要根据具体的情况进行选择。

  • 如果我们想要Redis仅仅作为纯内存的缓存来用,那么我们可以禁止RDB和AOF所有的持久化机制;

  • 通过RDB或AOF,都可以将Redis内存中的数据给持久化到磁盘上面来,然后可以将这些数据备份到别的地方去。我们一般会选择非当前机器的磁盘文件,这样可以避免由于机器损坏等因素导致磁盘数据和内存数据全部丢失,一般具有一定的隔离性。比如说将持久化的文件存放到云盘,云服务上等;

  • 如果Redis挂了,服务器上的内存和磁盘上的数据都丢了,我们就可以从事先备份好的存放在云盘、云服务等地方的数据拷贝回来,放到指定的目录中,然后重新启动Redis,Redis就会自动根据持久化数据文件中的数据,去恢复内存中的数据,继续对外提供服务;

  • 如果同时使用RDB和AOF两种持久化机制,那么在Redis重启的时候,会使用AOF来重新构建数据,因为AOF中的数据更加完整;

  • 也可以通过save或者bgsave命令同步或异步指定RDB快照生成。

  • AOF持久化,默认是关闭的,默认是打开RDB持久化;

  • appendonly yes,可以打开AOF持久化机制,在生产环境里面,一般来说AOF都是要打开的,除非你说随便丢个几分钟的数据也无所谓;

六、总结

上述,一起学习了两种支持持久化的方式,一方面我们需要通过快照或者AOF的方式对数据进行持久化,另一方面,我们还需要将持久化所得到的文件进行备份,备份到不同的服务器上,这样才可以尽可能的减少数据丢失的损失。


参考文章:

1、Redis in Action - [美] Josiah L.Carlsono
2、https://blog.csdn.net/johnstrive/article/details/78423595
3、https://blog.csdn.net/qq_34190023/article/details/82715705

相关文章:

  • 复利(结对2.0)
  • 为什么要重写hashCode()方法和equals()方法以及如何进行重写
  • 程序员下一门要学的编程语言Swift
  • Jenkins部署Maven多环境项目(dev、beta、prod)的参数设置
  • MATLAB地图工具箱学习总结(一)从地图投影说起
  • MySQL存储引擎MyISAM与InnoDB区别总结整理
  • Atitit。数据库 安全性 重要敏感数据加密存储解决方案
  • MySQL半同步复制原理配置与介绍
  • GIT 远程仓库:添加远程库、从远程库克隆
  • 用优雅的方式重装Windows 10不可使用的应用程序
  • 使用Generic Webhook Trigger插件实现Jenkins+WebHooks(码云)持续集成
  • Redis实战和核心原理详解(4)Redis存储Key的一种设计实现方式:模式匹配
  • 第一次冲刺阶段(六)
  • MyBatis关联映射:一对一、一对多
  • xshell配色Solarized Dark
  • 2018一半小结一波
  • Asm.js的简单介绍
  • bearychat的java client
  • C++类的相互关联
  • co模块的前端实现
  • github指令
  • HTML5新特性总结
  • Java编程基础24——递归练习
  • React as a UI Runtime(五、列表)
  • Redux系列x:源码分析
  • vue 个人积累(使用工具,组件)
  • Vue组件定义
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 构建二叉树进行数值数组的去重及优化
  • 记录:CentOS7.2配置LNMP环境记录
  • 目录与文件属性:编写ls
  • 前端_面试
  • 前端面试之闭包
  • 思维导图—你不知道的JavaScript中卷
  • 消息队列系列二(IOT中消息队列的应用)
  • 硬币翻转问题,区间操作
  • No resource identifier found for attribute,RxJava之zip操作符
  • 湖北分布式智能数据采集方法有哪些?
  • !!Dom4j 学习笔记
  • #图像处理
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (一)认识微服务
  • .gitignore文件设置了忽略但不生效
  • .Net Core webapi RestFul 统一接口数据返回格式
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .netcore 获取appsettings
  • .net开发时的诡异问题,button的onclick事件无效
  • .NET开源快速、强大、免费的电子表格组件
  • .NET面试题(二)
  • .NET中winform传递参数至Url并获得返回值或文件
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?