Redis持久化机制

发布时间 2023-09-06 21:09:48作者: 壹索007

1.怎么保证 Redis 挂掉之后再重启数据可以进行恢复?(持久化)

  很多时候我们需要持久化数据也就是将内存中的数据写入到硬盘里面,大部分原因是为了之后重用数据(比如重启机器、机器故障之后恢复数据),或者是为了防止系统故障而将数据备份到一个远程位置。

  Redis 不同于 Memcached 的很重要一点就是,Redis 支持持久化,而且支持 3 种持久化方式:

  • 快照(snapshotting,RDB)

  • 只追加文件(append-only file, AOF)

  • RDB 和 AOF 的混合持久化(Redis 4.0 新增)

 

2.RDB持久化

  Redis可以通过创建快照来获得存储在内存里面的数据在某个时间点上的副本。Redis 创建快照之后,可以对快照进行备份,可以将快照复制到其他服务器从而创建具有相同数据的服务器副本(Redis 主从结构,主要用来提高 Redis 性能),还可以将快照留在原地以便重启服务器的时候使用。

  快照持久化是Redis默认采用的持久化方式。

RDB的执行流程:(Redis 重启会通过加载dump.rdb文件恢复数据。)

 (1) redis根据配置文件,尝试去生成一个rdb快照文件。

 (2) fork一个子进程出来。

 (3) 子进程尝试将数据备份到rdb快照文件中。

 (4) 完成rdb快照文件的生成后,就替换之前旧的快照文件。

 

3.RDB 创建快照时会阻塞主线程吗?

  Redis提供了两个命令来生成RDB快照文件:

    ·save: 同步保存操作,会阻塞Redis主线程;

    ·bgsave: fork出一个子进程,子进程执行,不会阻塞Redis主线程,默认选项。

 

4.AOF持久化

  AOF持久化是指以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中命令达到恢复数据的目的。AOF的主要作用是解决了数据持久化的实时性,因此已成为主流的持久化方案。

  默认情况下Redis没有开启AOF方式的持久化(Redis6.0之后默认开启),可以通过 appendonly 参数开启:appendonly yes

  开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入到内存缓存 server.aof_buf 中,然后再写入到 AOF 文件中(此时还在系统内核缓存区未同步到磁盘),最后再根据持久化方式(fsync策略)的配置来决定何时将系统内核缓存区的数据同步到硬盘中的。

  只有同步到磁盘中才算持久化保存了,否则依然存在数据丢失的风险,比如说:系统内核缓存区的数据还未同步,磁盘机器就宕机了,那这部分数据就算丢失了。

  AOF 文件的保存位置和 RDB 文件的位置相同,都是通过 dir 参数设置的,默认的文件名是 appendonly.aof。

 

5.AOF工作基本流程

(1)命令追加(append):所有的写命令会追加到 AOF 缓冲区中。

(2)文件写入(write):将 AOF 缓冲区的数据写入到 AOF文件中。这一步需要调用write函数(系统调用),write将数据写入到了系统内核缓冲区之后直接返回了(延迟写)。

  注意!!此时并没有同步到磁盘。虽然提高了效率,但也带来了数据丢失的风险。

(3)文件同步(fsync):AOF 缓冲区根据对应的持久化方式(fsync 策略)向硬盘做同步操作。这一步需要调用 fsync 函数(系统调用), fsync 针对单个文件操作,对其进行强制硬盘同步,fsync 将阻塞直到写入磁盘完成后返回,保证了数据持久化。

(4)文件重写(rewrite):随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。

(5)重启加载(load):当 Redis 重启时,可以加载 AOF 文件进行数据恢复。

 

6.AOF持久化方式有哪些?fsync策略有哪些?

  在 Redis 的配置文件中存在三种不同的 AOF 持久化方式(fsync策略):

  (刷盘:同步 AOF 文件   后台线程:aof_fsync 线程)

  • appendfsync always:主线程调用 write 执行写操作后,后台线程立即会调用 fsync 函数刷盘,fsync 完成后线程返回,这样会严重降低 Redis 的性能(write + fsync)。
  • appendfsync everysec:主线程调用 write 执行写操作后立即返回,由后台线程每秒钟调用 fsync 函数(系统调用)同步一次 AOF 文件(write+fsyncfsync间隔为1s)
  • appendfsync no:主线程调用 write 执行写操作后立即返回,让操作系统决定何时进行同步,Linux 下一般为 30s一次(write但不fsyncfsync 时机由操作系统决定)。

  这 3 种持久化方式的主要区别在于 fsync 同步 AOF 文件的时机(刷盘)。为了兼顾数据和写入性能,可以考虑 appendfsync everysec 选项 ,让 Redis 每秒同步一次 AOF 文件,Redis 性能受到的影响较小。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。

 

  从 Redis 7.0.0 开始,Redis 使用了 Multi Part AOF 机制。就是将原来的单个 AOF 文件拆分成多个 AOF 文件。在 Multi Part AOF 中,AOF 文件被分为三种类型,分别为:

  • BASE:基础 AOF 文件,一般由子进程通过重写产生,该文件最多只有一个。
  • INCR:增量 AOF 文件,一般会在 AOFRW 开始执行时被创建,该文件可能存在多个。
  • HISTORY:表示历史 AOF 文件,每次 AOFRW 成功完成时,本次 AOFRW 之前对应的 BASE 和 INCR AOF 都将变为 HISTORY,HISTORY 类型的 AOF 会被 Redis 自动删除。

 

7.AOF日志如何实现

  关系型数据库(如 MySQL)通常都是执行命令之前记录日志(方便故障恢复),而 Redis AOF 持久化机制是在执行完命令之后再记录日志。

为什么是在执行完命令之后记录日志呢?

  ·避免额外的检查开销,AOF 记录日志不会对命令进行语法检查;

  ·在命令执行完之后再记录,不会阻塞当前的命令执行。

这样也带来了风险

  ·如果刚执行完命令 Redis (此时在系统内核缓冲区)就宕机会导致对应的修改丢失;

  ·可能会阻塞后续其他命令的执行(AOF 记录日志是在 Redis 主线程中进行的)。

 

8.AOF重写了解吗

  AOF文件会变得越来越大,数据恢复会变慢。当 AOF 变得太大时,Redis能够在后台自动重写 AOF产生一个新的AOF文件,新旧两个AOF文件保存的数据相同,但新AOF文件没有了冗余命令, 体积更小。

  AOF重写是通过读取数据库中的键值对实现,程序无须对现有AOF文件进行任何读入、分析或写入操作。

  在执行BGREWRITEAOF命令时,Redis服务器会维护一个AOF重写缓冲区,该缓冲区会在子进程创建新AOF文件期间,记录服务器执行的所有写命令。当子进程完成创建新AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新AOF文件的末尾,使得新的AOF文件保存的数据库状态与现有的数据库状态一致。最后,服务器用新的AOF文件替换旧的AOF文件,以此来完成AOF文件重写操作。

  (一边生成新AOF,需要存的指令先放缓冲区,新AOF生成好之后,直接放后面)

 

9.AOF 校验机制了解吗?

  AOF 校验机制是 Redis 在启动时对 AOF 文件进行检查,以判断文件是否完整,是否有损坏或者丢失的数据。这个机制的原理是通过使用一种叫做 校验和(checksum) 的数字来验证 AOF 文件。这个校验和是通过对整个 AOF 文件内容进行 CRC64 算法计算得出的数字。如果文件内容发生了变化,那么校验和也会随之改变。如果发现文件有问题,Redis 就会拒绝启动并提供相应的错误信息。


10.如何选择 RDB 和 AOF?

RDB: 经过压缩的二进制数据,文件小,适合数据备份,灾难恢复;恢复数据直接解析还原即可,速度较快。

AOF:可以实现秒级持久化,实时性更好;写入过程是追加到AOF文件,操作轻量;可读性强。

RDB比AOF 优秀的地方:

  RDB文件存储的内容是经过压缩的二进制数据, 保存着某个时间点的数据集,文件很小,适合做数据的备份,灾难恢复。AOF文件存储的是每一次写命令,类似于MySQL的binlog日志,通常比 RDB 文件大很多。当AOF 变得太大时,Redis 能够在后台自动重写 AOF。新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。不过, Redis 7.0 版本(Multi-part AOF)之前,如果在重写期间有写入命令,AOF可能会使用大量内存,重写期间到达的所有写入命令都会写入磁盘两次。

  使用RDB文件恢复数据,直接解析还原数据即可,不需要一条一条地执行命令,速度非常快。而 AOF则需要依次执行每个写命令,速度非常慢。也就是说,与AOF相比,恢复大数据集的时候,RDB速度更快。

AOF比RDB优秀的地方:

  RDB的数据安全性不如AOF,没有办法实时或者秒级持久化数据。生成 RDB 文件的过程是比较繁重的,虽然 BGSAVE子进程写入 RDB 文件的工作不会阻塞主线程,但会对机器的CPU资源和内存资源产生影响,严重的情况下甚至会直接把Redis服务干宕机。AOF 支持秒级数据丢失(取决 fsync 策略,如果是 everysec,最多丢失 1 秒的数据),仅仅是追加命令到AOF文件,操作轻量。

  RDB文件是以特定的二进制格式保存的,并且在Redis版本演进中有多个版本的RDB,所以存在老版本的 Redis 服务不兼容新版本的RDB格式的问题。

  AOF以一种易于理解和解析的格式包含所有操作的日志。你可以轻松地导出AOF文件进行分析,你也可以直接操作AOF文件来解决一些问题。比如,如果执行FLUSHALL命令意外刷新了所有内容后,只要AOF文件没有被重写,删除最新命令并重启即可恢复之前的状态。

选择:

  • Redis 保存的数据丢失一些也没什么影响的话,可以选择使用 RDB。
  • 不建议单独使用 AOF,因为时不时地创建一个 RDB 快照可以进行数据库备份、更快的重启以及解决 AOF 引擎错误。
  • 如果保存的数据要求安全性比较高的话,建议同时开启 RDB 和 AOF 持久化或者开启 RDB 和 AOF 混合持久化。

 

11.Redis 4.0 对于持久化机制做了什么优化?

  由于RDB和AOF各有优势,于是,Redis 4.0开始支持RDB和AOF的混合持久化(默认关闭,可以通过配置项 aof-use-rdb-preamble 开启)。

  如果把混合持久化打开,AOF重写的时候就直接把 RDB的内容写到AOF文件开头。

  好处:可以结合RDB和AOF的优点, 快速加载同时避免丢失过多的数据。

  缺点:AOF里面的RDB部分是压缩格式不再是AOF格式,可读性较差。