Redis 详解持久化机制

🎈 持久化策略

RDB内存快照)

AOF(追加文件)

🎈 RDB

  • 内存快照(默认开启

  • 就是把某一时刻的数据和状态以文件的方式写到磁盘上,就是快照。这样一来即使故障宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。

  • 这个快照文件称为 RDB 文件(dump.rdb),其中,RDB 就是 Redis DataBase 的缩写

分为自动触发和主动触发

  • 自动触发:通过服务端的配置文件(redis.conf)指定触发 RDB 条件,本质是通过达到一定条件后自动触发持久化,这个条件规则就是 M 秒内 N 个 key 发生了变化。

  • 主动触发:savebgsave命令让服务器生成 rdb 文件;

1、redis.conf 配置文件

 

#是否压缩rdb文件 
rdbcompression yes 

#rdb文件的名称 
dbfilename redis-6379.rdb 

#rdb文件保存目录,物理恢复,一定服务和备份分级隔离 
dir ~/redis/

2、save

save 命令是同步操作,同步数据到磁盘上,阻塞

  1. 当客户端向服务器发送 save 命令请求进行持久化时,服务器会阻塞 save 命令之后的其他客户端的请求,直到数据同步完成

  2. 如果数据量太大,同步数据会执行很久,而这期间 Redis 服务器也无法接收其他请求,所以,最好不要在生产环境使用save命令。

3、bgsave

bgsave 命令是异步操作,异步将数据同步到磁盘上,不阻塞

  • 当客户端发服务发出 bgsave 命令时,Redis 服务器主进程会 forks 一个子进程来数据同步,在将数据保存到 rdb 文件之后,子进程会退出

  • 所以,与 save 命令相比,Redis 服务器在处理 bgsave 采用子线程进行 IO 写入,而主进程仍然可以接收其他请求,但 forks 子进程是同步的,所以 forks 子进程时,一样不能接收其他请求,这意味着,如果 forks 一个子进程花费的时间太久(一般是很快的),bgsave 命令仍然有阻塞其他客户的请求的情况发生

fork:在 Linux 系统中,调用 fork() 时,会创建出一个新进程,称为子进程,子进程会拷贝父进程的 page table。如果进程占用的内存越大,进程的 page table 也会越大,那么 fork 也会占用更多的时间。如果 Redis 占用的内存很大,那么在 fork 子进程时,则会出现明显的停顿现象

4、哪些情况会触发 RDB 快照

  • 配置文件中默认的快照配置(redis.conf);

  • 手动savebgsave命令;

  • 执行flushall/flushdb命令也会产生 dump.rdb 文件,但是里面是空的,无意义;

  • 执行shutdown且没有设置开启 AOF 持久化;

  • 主从复制时,主节点自动;

5、快照生成期间, 数据被修改了, 怎么同步最新的数据

Redis 就会借助操作系统提供的写时复制技术(Copy-On-Write, COW),在执行快照的同时,正常处理写操作, 新写的数据会 copy 一份副本出来, 最终写进 RDB 中

6、RDB 文件生成流程

  1. 生成临时 rdb 文件,并写入数据。

  2. 完成数据写入,用临时文代替代正式 rdb 文件。

  3. 删除原来的 rdb 文件。

7、怎么禁用快照

使用命令:redis-cli config set save""

8、其他配置文件了解

#默认yes #如果配置成no,表示你不在乎数据不一致或者其他的手段发现和控制这种不一致,那么在快照写入失败时,也能确 #保redis继续接受新的请求 stop-writes-on-bgsave-error yes #默认yes #对于存储到磁盘中的快照,可以设置是否进行压缩存储,如果是的话,redis会采用LZF算法进行压缩。如果你不想 #消耗CPU来进行压缩的话,可以设置为关闭此功能 rdbcompression yes #默认yes #在存储快照后,还可以让redis使用CRC64算法进行数据效验,但是这样做会增加大约10%的性能消耗。如果希望获取#到最大的性能提升,可以关闭此功能 #在没有持久性的情况下删除复制中使用的RDB文件启用。默认情况下no,此选项是禁用的。 rdb-del-sync-files

9、优点和缺点

✔优点:

  1. 与 AOF 方式相比,通过 rdb 文件恢复数据比较快。(因为是二进制压缩文件)

  2. rdb 文件非常紧凑,适合于数据备份。(因为是二进制压缩文件)

❌缺点:

  1. 如果服务器宕机的话,采用 RDB 的方式会造成某个时段内数据的丢失,比如我们设置 10 分钟同步一次或 5 分钟达到 1000 次写入就同步一次,那么如果还没达到触发条件服务器就死机了,那么这个时间段的数据会丢失。

  2. 使用 save 命令会造成服务器阻塞,直接数据同步完成才能接收后续请求。

  3. 使用 bgsave 命令在 forks 子进程时,如果数据量太大,forks 的过程也会发生阻塞,另外,forks 子进程会耗费内存。

10、注意和补充

❓怎么恢复:

  • 将备份文件(dump.rdb)移动到 redis 安装目录并启动服务即可

❗注意:

  • 不可以把备份文件 dump.rdb 和生产 redis 服务器放在同一台机器,必须分开各自存储,以防上产机物理损坏后备份文件也挂了

🔹其他:

  • 可以通过lastsave 命令获取最后一次成功执行快照的时间,值是时间戳

  • 通过date -d@时间戳命令转换成日期格式

🎈 AOF

AOF 是 append olny file 的缩写

以日志的形式来记录每个写操作,将 Redis 执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,追加保存到以后缀 aof 文件的末尾(redis7 会有三个文件),在 redis 启动会读取该文件,会加载运行 aof 文件的命令,达到恢复数据的工作

AOF 持久化功能的实现可以分为三个步骤:命令追加、文件写入、文件同步

1、AOF 持久化流程

  1. 客户端作为命令的来源,会有多个源头以及源源不断的请求命令

  2. 在这些命令到达服务端以后并不是直接写入 AOF 文件,会将这些命令先放入 AOF 缓存中进行保存,这里的 AOF 缓冲区实际上是内存中的一片区域,存在的目的是当这些命令达到一定量以后在写入磁盘,避免频繁的磁盘 IO 操作,这也就是为什么会有文件写入和文件同步俩个操作的主要原因

  3. AOF 缓冲会根据 AOF 缓冲区同步文件的三种策略将命令写入磁盘的 AOF 文件

  4. 随着写入 AOF 内容的增加为了避免文件膨胀,会根据规则进行命令的合并(又称 AOF 重写),从而祈祷 AOF 文件压缩的目的

  5. 当 redis server 服务器重启的时候会从 AOF 文件载入数据

  • 命令追加:服务器在执行完一个命令之后,会将执行的写命令追加到服务器状态的 AOF 缓冲区(aof_)的末尾

  • Linux 操作系统中为了提升性能,使用了页缓存(page cache)。当我们将 aof_buf 的内容写到磁盘上时,此时数据并没有真正的落盘,而是在 page cache 中,为了将 page cache 中的数据真正落盘,需要执行 fsync / fdatasync 命令来强制刷盘。这边的文件同步做的就是刷盘操作,或者叫文件刷盘可能更容易理解一些

2、开启 AOF 持久化

Redis 默认是不开启 AOF 持久化的,可以更改配置文件进行开启,如下面图中所示

3、三种写入策略

以上三种写入策略只是在不同时机去调用 OS 的 fsync()函数

  • Always 同步写回,每个写命令执行完立主线程就会执行 fsync()函数立刻同步地将日志写回磁盘

  • Everysec 每秒写回,每个写命令执行完,只是先把日志写到 AOF 文件的内存缓冲区,每隔 1 秒把缓冲区中的内容写入磁盘,会创建一个异步线程来执行 fsync()函数

  • No 不执行 fsync()函数,执行 write()函数写入到 OS chache,至于什么时候刷盘,交给 OS 自己决定

  1. write 只要把日志记录写到内核缓冲区,就返回了, 并不需要等待日志实际写回到磁盘;

  2. fsync 需要把日志记录写回到磁盘后才能返回,时间较长。

4、Redis7.0 核心特性 AOF

MP-AOF 就是将原来的单个 AOF 文件拆分成多个 AOF 文件,主要分为三种类型

  • BASE:表示基础 AOF,它一般由子进程通过重写产生,该文件最多只有一个

  • INCR:表示增量 AOF,它一般会在 AOFRW 开始执行时被创建,该文件可能存在多个

  • HISTORY:表示历史 AOF,它有 BASE 和 INCR AOF 变化而来,每次 AOFRW 成功完成时,本次 AOFRW 之前对应的 BASE 和 INCR AOF 都将变为 HISTORY,HISTORY 类型的 AOF 会被 Redis 自动删除。

为了管理这些 AOF 文件,引入了一个 manifest(清单)文件来跟踪、管理这些 AOF。同时,为了便于 AOF 备份和拷贝,我们将所有的 AOF 文件和 manifest 文件放入一个单独的文件目录中,目录名有 appenddirname 配置

5、AOF 文件重写

  • 由于 AOF 持久化是 Redis 不断将写命令记录到 AOF 文件中,随着 Redis 不断地进行,AOF 的文件会越来越大,文件越大,占用服务器内存越大以及 AOF 恢复要求的时间越长

  • 为了解决这个问题,Redis 新增了重写机制,当 AOF 文件的大小超过所制定的峰值时,Redis 就会自动启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集

  • 同样也可以手动命令bgrewriteaof来重写

比如对一个 key 多次执行 incr 命令,这时候 aof 保存每一次命令到文件中,文件就会越来越大。

为了解决这个问题,Redis 支持 aof 文件重写,通过重写 aof,可以生成一个恢复当前数据的最少命令集,比如上面的例子中那么多条命令,可以重写为

5.1、重写的时机

  • 默认配置是当 AOF 文件大小是上次 rewrite 后大小的一倍并且文件大于 64M 后

  • 客户端向服务器发送bgrewriteaof命令

5.2、重写流程

AOF 文件重写并不是对原文件进行重新整理,而是直接读取服务器现有的键值对,然后用一条命令去代替之前记录这个键值对的多条命令,生成一个新的文件后去替换原来的 AOF 文件。

  1. 在重写开始前,redis 会创建(fork)一个“重写子进程”,这个子进程会读取现有的 AOF 文件,并将其包含的指令进行分析压缩并写入到一个临时文件中。

  2. 与此同时,主工作进程会将新接收到的写指令一边累积到内存缓冲区中,一边继续写入到原有的 AOF 文件中,这样做是保证原有的 AOF 文件的可用性,避免在重写过程中出现意外。

  3. 当"重写子进程"完成重写工作后,它会给父进程发一个信号,父进程收到信号后就会将内存中缓存的写指令追加到新 AOF 文件中,

  4. 当追加结束后,redis 就会用新 AOF 文件来代替旧 AOF 文件,之后再有新的写指令,就都会追加到新的 AOF 文件中了。

  5. 重写 AOF 文件的操作,并没有读取旧的 AOF 文件,而是将整个内存中的数据库内容用命令的方式重写一个新的 AOF 文件,这点和快照有点类似

5.3 AOF 后台重写存在的问题

❗问题:

AOF 后台重写使用子进程进行重写,解决了主进程阻塞的问题,但是仍然存在另一个问题:子进程在进行 AOF 重写期间,服务器主进程还需要继续处理命令请求,新的命令可能会对现有的数据库状态进行修改,从而使得当前的数据库状态和重写后的 AOF 文件保存的数据库状态不一致。

✔解决方案:

为了解决上述问题,Redis 引入了 AOF 重写缓冲区(aof_rewrite_buf_blocks),这个缓冲区在服务器创建子进程之后开始使用,当 Redis 服务器执行完一个写命令之后,它会同时将这个写命令追加到 AOF 缓冲区和 AOF 重写缓冲区。

6、怎么禁用 AOF

#禁用aof持久化模式下,我们仍然可以使用命令bgrewriteafo生成aof文件 appendonly no

7、AOF 优点

  • AOF 只是追加日志文件,因此对服务器性能影响较小,速度比 RDB 要快,消耗的内存较少

  • AOF 更加持久化,只会丢失一秒钟的写入

  • AOF 日志是一个仅附加日志,因此不会出现寻道问题,不会出现断电时出现损坏问题,即使由于某种原因日志以协议班的命令结尾,redis-check-afo 工具也能够轻松修复它

  • AOF 重写机制,缩小内存

  • AOF 以易于理解和解析的格式依次包含所有操作的日志,甚至可以轻松导出 AOF 文件

  • 即使不小心使用了 FLUSHALL 命令刷新了所有内容,只要在此期间没有执行日志重写,仍然可以通过停止服务器、删除最新命令并重新启动 Redis 来保存数据集

8、AOF 缺点

  • AOF 方式生成的日志文件太大,即使通过 AOF 重写,文件体积仍然很大。

  • 恢复数据的速度比 RDB 慢,需要解析语句

  • 如果配置的是 always 策略, 需要持久化成功后才返回成功, 性能更慢

🎈 混合持久化

一般生产环境采用新特性:混合持久化

1、描述

  • 混合持久化并不是全新的持久化格式,而是对已有方式的优化,混合持久化只发生于 AOF 重写过程。使用了混合持久化,重写后的新 AOF 文件前半段是 RDB 格式的全量数据,后半段是 AOF 格式的增量数据。

  • 整体格式:RDB file + AOF tail

  • 结论:RDB 镜像做全量持久化,AOF 做增量持久化

  • 白话:先使用 RDB 进行快照存储,然后使用 AOF 持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的 RDB 记录

2、开启

更给配置文件aof-use-rdb-preamble yes开启混合持久化,在 redis4.0 刚引入时,默认是关闭混合持久化,redis5 中默认是开启的。

3、流程

  • 混合持久化本质是通过 AOF 后台重写(bgrewriteaof 命令)完成的,不同的是当开启混合持久化时,fork 出的子进程先将当前全量数据以 RDB 方式写入新的 AOF 文件,然后再将 AOF 重写缓冲区(aof_rewrite_buf_blocks)的增量命令以 AOF 方式写入到文件,写入完成后通知主进程将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。

  • 在数据恢复过程中,如果 AOF 文件开始是 RDB 格式,则先加载 RDB 格式内容,再加载 AOF 格式内容。如果 AOF 文件开头不是 RDB 格式,则直接用 AOF 格式加载整个文件

🎈 持久化文件损坏

在写入 aof 日志文件时,如果 Redis 服务器宕机了,则 aof 日志文件会出现格式错误,在重启 Redis 服务器时,就会拒绝载入这个 aof 文件,同样 rdb 文件也可能出现损坏。

✔解决方案:

  1. 备份现在的 aof 和 rdb 文件以防万一

  2. 通过redis-check-rdb 命令可以修改损坏的 rdb 文件(在 redis 安装 bin 目录下)

  3. 通过redis-check-aof -fix file.aof 命令可以修改损坏的 aof 文件(在 redis 安装 bin 目录下)

🎈 RDB 和 AOF 总结

  1. RDB 优点:采用⼦进程生成 RDB ⽂件,减少对 Redis 主线程的阻塞,保证 Redis 性能;RDB 是内存快照,恢复效率⾼。

  2. RDB 不⾜:RDB 是间隔⼀段时间⽣成⼀次,两次 RDB 创建之前,如果 Redis 发⽣故障,会发⽣数据丢失。

  3. AOF 优点:采用 always 配置项时,可以每个命令做⼀次持久化,可靠性相比 RDB 更⾼。

  4. AOF 不足:AOF ⽂件较⼤,会触发 AOF 重写,重写时会竞争内存资源;AOF 恢复是回放命令操作,恢复速度慢于 RDB。

RDBAOF 两种方式都开启时,Redis 会优先使用 AOF 日志来恢复数据,因为 AOF 保存的文件比 RDB 文件更完整

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值