文章目录
前言
Redis支持RDB和AOF两种持久化机制,持久化功能有效地避免因进程退出造成的数据丢失问题,当下次重启时利用之前持久化的文件即可实现数据恢复。理解掌握持久化机制对于Redis运维非常重要。
一.持久化思路
传统的mysql我们是把数据存储到硬盘中,redis的一个最重要的特点就是快,我们也会在硬盘中存储,也会在内存中存储,具体我们是怎么做的呢?
当要插入一个数据的时候,就需要把这个数据,同时写入内存和硬盘。
当要查询某个数据的时候,直接从内存读。
硬盘的数据知识在redis重启的时候,用来恢复内存中数据的。
二.Redis持久化的策略
RDB => Redis DataBase
RDB持久化是在指定的时间间隔内,定时将Redis在内存中的数据库状态(键值对等信息)以快照的形式保存到磁盘上。这种方式可以理解为在某个时间点对Redis的数据进行“拍照”,并保存为二进制文件。当Redis重启时,可以从这些快照文件中恢复数据。RDB方式具有体积小、恢复速度快的特点,对性能影响较小,但可能在两次快照之间发生故障时丢失部分数据。
换句话说,就是定期备份。比如每个月我们会把自己认为的资料备份一份。AOF =>Append Only File
AOF持久化则是将Redis服务器执行的每一条写命令以追加的方式记录到一个文本文件中。当Redis重启时,只需将这些写命令从前到后重新执行一遍,即可恢复数据。这种方式具有实时性更好的优点,即当进程意外退出时丢失的数据更少,因此是目前主流的持久化方式。但AOF文件可能会比RDB文件大,且恢复数据可能需要更长的时间。
换句话说实时备份。只要每次下载了资料,就会马上备份一次。
三.RDB持久化策略
RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。
快照的概念:Redis给内存中当前这些数据,拍个照片,生成一个文件,存储在硬盘中,后续Redis一旦重启了,就可以根据刚才的快照,就能把内存中的数据恢复过来。
手动触发:手动触发分别对应save和bgsave命令:
自动触发:在Redis配置文件中,设置一下,让Redis每隔多长时间/每产生多少次修改就触发。
3.1 触发机制
手动触发分别对应save和bgsave命令
save命令:阻塞当前Redis服务器,直到RDB过程完成为止,对于内存
比较大的实例会造成长时间阻塞,线上环境不建议使用。
bgsave命令:Redis进程执行fork操作创建子进程,RDB持久化过程由子
进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。
3.2 流程说明
bgsave是主流的触发RDB持久化方式,
- 判断当前是否已经存在其他正在工作的子进程。如果有一个子进程正在执行bgsave,此时就把当前bgsave返回。
- 如果没有其他工作的子进程,就通过fork这样的系统调用,创建出一个子进程。
- 子进程负责进行写文件,生成快照的过程,父进程继续接受客户端的请求,继续正常提供服务。
- 子进程完成整体的持久化过程之后,就会通知父进程,工作完成之后,父进程会更新一些统计信息,子进程就可以结束销毁了。
3.3 RDB文件的处理
RDB文件保存在dir配置指定的目录下,文件名通过dbfilename配置指定。可以通过执行config set dir{newDir}和config setdbfilename{newFileName}运行期动态执行,当下次运行时RDB文件会保存到新目录。
这里的镜像文件是二进制文件格式的,把内存的中的数据,以压缩的形式,保存到二进制文件中,后续redis服务器重新启动,就会尝试加载这个rdb文件。
redis提供了redis-check-rdb的文件检查工具。
回到最开始的流程演示
当执行 生成 rdb 镜像 操作的时候,
此时就会把要生成的快照数据,先保存到一个临时文件中
当这个快照生成完毕之后,再删除之前的 rdb 文件,把新生成的临时的 rdb 文件名字改成刚才的 dump.rdb 。
3.4 RDB持久化演示
这里我们先去看redis下的redis.conf的配置文件,去看一下生成的rdb文件张什么样子。
切换到这个目录下,我们就看到了,目录确实有一个rdb文件
打开发现是一个二进制文件编码。
接下来,我们模拟一个场景,我们向数据库里面插入数据,看看rdb文件,会不会有什么
变化。
这时候,我们可以使用bgsave手动触发这个机制。
再次查看文件,显而易见的已经发生了变化
3.5 RDB持久化场景
- 手动执行save和 bgsave 触发一次生成快照
插入新的key,不手动执行bgsave。
我们这里手动杀死redis服务。
再次进入redis客户端。看看我们刚才插入的数据是否生效。
因为我们关闭redis服务的时候,我们也会触发快照机制。
–bgsave的操作会创建子进程,子进程会完成持久化操作。
这里的持久化操作是指把数据写入新的文件中,使用新的文件替换旧的文件。具体的形式,用linux的stat命令,查看文件的版本号即可。
实际上我们这里的文件已经改变了。
–通过配置自动生成rdb快照
如果我们手动破坏rdb文件,会怎样?
手动破坏 RDB(Redis 数据库)文件会对您的 Redis 数据和 Redis 服务器的整体运行造成严重后果。以下是可能发生的情况:
- 数据丢失和不一致:
损坏的 RDB 文件将包含无效或不完整的数据,导致数据丢失和不一致。
当 Redis 尝试加载损坏的 RDB 文件时,它可能无法启动或崩溃,使您存储的数据无法访问。
根据损坏的程度,您可能会丢失大量数据甚至整个数据集。
- 服务器不稳定和崩溃:
尝试使用损坏的 RDB 文件会导致 Redis 行为不可预测,并可能导致频繁崩溃或服务器宕机。
服务器可能难以处理请求并维护数据完整性,从而影响应用程序的性能和可靠性。
在严重的情况下,Redis 服务器可能会完全失败,需要从备份中完全恢复或导致数据完全丢失。
- 恢复挑战和数据丢失:
从损坏的 RDB 文件中恢复可能具有挑战性或根本不可能,具体取决于损坏的程度。
如果损坏程度较小,您可以使用专用工具或技术修复文件。
但是,如果损坏程度严重,您可能需要依靠备份或面临潜在的数据丢失。
3.5 优点和缺点
优点:
- RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照。非常适用于备份,全量复制等场景。比如每6小时执行bgsave备份,并把RDB文件拷贝到远程机器或者文件系统中(如hdfs),用于灾难恢复。
缺点:
- RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,频繁执行成本过高。
- RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题。
- 对RDB不适合实时持久化的问题。
四.AOF的持久化策略
AOF(append only file)持久化:以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,目前已经是Redis持久化的主流方式。理解掌握好AOF持久化机制对我们兼顾数据安全性和性能非常有帮助。
4.1 什么是AOF
- AOF机制并非直接让工作线程把数据写入硬盘,而是先写入一个内存的缓冲区,积累一波之后,再统一写入硬盘。
- 硬盘上读写数据,顺序读写的速度还是移交快的。AOF是每次把新的操作写入原有文件的末尾。
4.2 AOF 的执行流程
AOF的工作流程操作:命令写入
(append)、文件同步(sync)、文件重写(rewrite)、重启加载(load)
4.3 AOF的刷新策略
Redis提供了多种AOF缓冲区同步文件策略
系统调⽤ write 和 fsync 说明:
- write 操作会触发延迟写(delayed write)机制。Linux 在内核提供⻚缓冲区⽤来提供硬盘 IO 性
能。write 操作在写⼊系统缓冲区后⽴即返回。同步硬盘操作依赖于系统调度机制,例如:缓冲区⻚空间写满或达到特定时间周期。同步⽂件之前,如果此时系统故障宕机,缓冲区内数据将丢失。 - Fsync 针对单个⽂件操作,做强制硬盘同步,fsync 将阻塞直到数据写⼊到硬盘。
- 配置为 always 时,每次写⼊都要同步 AOF ⽂件,性能很差,在⼀般的 SATA 硬盘上,只能⽀持⼤约⼏百 TPS 写⼊。除⾮是⾮常重要的数据,否则不建议配置。
- 配置为 no 时,由于操作系统同步策略不可控,虽然提⾼了性能,但数据丢失⻛险⼤增,除⾮数据重要程度很低,⼀般不建议配置。
- 配置为 everysec,是默认配置,也是推荐配置,兼顾了数据安全性和性能。理论上最多丢失 1 秒的
数据。
4.4 重写机制
随着命令不断写⼊ AOF,⽂件会越来越⼤,为了解决这个问题,Redis 引⼊ AOF 重写机制压缩⽂
件体积。AOF ⽂件重写是把 Redis 进程内的数据转化为写命令同步到新的 AOF ⽂件。
AOF重写过程可以手动触发和自动触发:
- 手动触发:直接调用bgrewriteaof命令。
- 自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参
数确定自动触发时机
具体流程:
流程说明:
- 执⾏ AOF 重写请求。
如果当前进程正在执⾏ AOF 重写,请求不执⾏。如果当前进程正在执⾏ bgsave 操作,重写命令延迟到 bgsave 完成之后再执⾏。 - ⽗进程执⾏ fork 创建⼦进程。
- 重写
a. 主进程 fork 之后,继续响应其他命令。所有修改操作写⼊ AOF 缓冲区并根据 appendfsync 策略同步到硬盘,保证旧 AOF ⽂件机制正确。
b. ⼦进程只有 fork 之前的所有内存信息,⽗进程中需要将 fork 之后这段时间的修改操作写⼊
AOF 重写缓冲区中。 - ⼦进程根据内存快照,将命令合并到新的 AOF ⽂件中。
- ⼦进程完成重写
a. 新⽂件写⼊后,⼦进程发送信号给⽗进程。
b. ⽗进程把 AOF重写缓冲区内临时保存的命令追加到新 AOF ⽂件中。
c. ⽤新 AOF ⽂件替换⽼ AOF ⽂件。
4.5 重启加载
流程说明:
1)AOF持久化开启且存在AOF文件时,优先加载AOF文件,打印如下
2)AOF关闭或者AOF文件不存在时,加载RDB文件,打印如下日志:
3)加载AOF/RDB文件成功后,Redis启动成功。
4)AOF/RDB文件存在错误时,Redis启动失败并打印错误信息。