Redis 持久化

发布于:2025-02-20 ⋅ 阅读:(37) ⋅ 点赞:(0)
Redis 提供了多种持久化机制,主要包括 RDB(Redis Database)、AOF(Append Only File)以及混合持久化机制, 持久化功能有效地避免因进程退出造成数据丢失问题,当下次重启时利⽤之前持久化的⽂件即可实现数据恢复。

RDB

RDB 持久化过程为,在指定的时间间隔内 Redis 将 内存中的数据保存到磁盘上的一个 RDB 文件(通常是 .rdb 文件)。这个文件是一个二进制文件,包含了当前 Redis 数据库的完整数据快照。 触发 RDB 持久化过程分为⼿动触发和⾃动触发。

RDB 文件的处理

  • 保存:RDB ⽂件保存在 dir 配置指定的⽬录(默认 /var/lib/redis/)下,⽂件名通过 dbfilename 配置(默认 dump.rdb)指定。可以通过执⾏ config set dir {newDir} 和 config set dbfilename {newFilename} 运⾏期间动态执⾏,当下次运⾏时 RDB ⽂件会保存到新⽬录。
  我们可以查看配置文件 /etc/redis/redis.conf 发现工作目录如下:
而redis 生成的 rdb 文件就存放在该工作目录中,默认为 dump.rdb,并且 rdb 文件只有一个。
  • 压缩:Redis 默认采⽤ LZF 算法对⽣成的 RDB ⽂件做压缩处理,压缩后的⽂件远远⼩于内存⼤⼩,默认开启,可以通过参数 config set rdbcompression {yes|no} 动态修改。
  • 校验:如果 Redis 启动时加载到损坏的 RDB ⽂件会拒绝启动。这时可以使⽤ Redis 提供的 redis-check-dump ⼯具检测 RDB ⽂件并获取对应的错误报告。

RDB 的优缺点

RDB 的优点

  • 数据恢复:RDB 文件是一个完整的数据快照,可以用于数据恢复。如果 Redis 服务器崩溃,可以通过加载 R 文件DB恢复数据。

  • 备份方便:RDB 文件是二进制格式,体积相对较小,便于备份和传输。

  • 性能优势:在使用 BGSAVE 时,主进程不会被阻塞,因此对 Redis 性能的影响较小。

RDB 的缺点

  • 数据丢失风险:如果 Redis 服务器在两次 RDB 持久化之间崩溃,可能会丢失部分数据,因为 RDB 是基于快照的,只有在快照完成后才会保存数据。

  • 持久化时间间隔:如果配置的持久化时间间隔过长,可能会导致丢失更多数据;如果时间间隔过短,会增加磁盘 I/O 负担。

  • 大文件处理:对于大型数据库,RDB 文件可能会非常大,这可能会导致保存和加载时间较长。

触发机制

手动触发

⼿动触发分别对应 save 和 bgsave 命令:
  • save 命令:阻塞当前 Redis 服务器,直到 RDB 过程完成为⽌,对于内存⽐较⼤的实例造成⻓时间阻塞,基本不采⽤。
  • bgsave 命令:Redis 进程执⾏ fork 操作创建⼦进程,RDB 持久化过程由⼦进程负责,完成后⾃动结束。阻塞只发⽣在 fork 阶段,⼀般时间很短。Redis 内部的所有涉及 RDB 的操作都采⽤类似 bgsave 的⽅式。

  1. 执⾏ bgsave 命令,Redis ⽗进程判断当前进是否存在其他正在执⾏的⼦进程,如 RDB/AOF ⼦进程,如果存在 bgsave 命令直接返回。
  2. ⽗进程执⾏ fork 创建⼦进程,fork 过程中⽗进程会阻塞,通过 info stats 命令查看latest_fork_usec 选项,可以获取最近⼀次 fork 操作的耗时,单位为微秒。
  3. ⽗进程 fork 完成后,bgsave 命令返回 "Background saving started" 信息并不再阻塞⽗进程,可以继续响应其他命令。
  4. ⼦进程创建 RDB ⽂件,根据⽗进程内存⽣成临时快照⽂件,完成后对原有⽂件进⾏原⼦替换。执⾏ lastsave 命令可以获取最后⼀次⽣成 RDB 的时间,对应 info 统计的 rdb_last_save_time 选项。
  5. 进程发送信号给⽗进程表⽰完成,⽗进程更新统计信息,并将更新信息合并到 dump.rdb 文件中。

使用示例如下

在 /var/lib/redis 中就会生成新的 dump.rdb 文件

文件内容如下,redis 在重新启动的时候就会加载 rdb 文件的内容,恢复原先内存中的状态

自动触发

除了⼿动触发之外,Redis 运⾏⾃动触发 RDB 持久化机制,这个触发机制才是在实战中有价值的。我们可以先查看 reids 的配置文件 /etc/redis/redis.conf,我们可以使用 vim 查看该文件内容

  • 使⽤ save 配置。如 "save m n" 表⽰至少 m 秒内数据集发⽣了至少 n 次修改,⾃动 RDB 持久化。如下图中配置了三项,如至少 900 秒内数据集发⽣了至少 1 次修改。

  • 从节点进⾏全量复制操作时,主节点⾃动进⾏ RDB 持久化,随后将 RDB ⽂件内容发送给从结点。
  • 执⾏ shutdown 命令关闭 Redis 时,执⾏ RDB 持久化。这就意味着正常退出时可以自动生成 rdb 文件,但是异常退出时(如使用 kill -9 或服务器断电)就不会生成快照,内存中尚未保存的数据就会丢失。

AOF

AOF(Append Only File)持久化的核心思想是 以独⽴⽇志的⽅式记录每次写命令,重启时再重新执⾏ AOF ⽂件中的命令达到恢复数据的⽬的。AOF 的主要作⽤是解决了数据持久化的实时性,⽬前已经是 Redis 持久化的主流⽅式。

使用 AOF

开启 AOF 功能需要在配置文件 /etc/redis/redis.conf 中设置配置:appendonly yes,默认不开启如下所示。
AOF ⽂件名通过 appendfilename 配置(默认是 appendonly.aof)设置。保存⽬录同 RDB 持久化⽅式⼀致,通过 dir 配置指定。AOF 的⼯作流程操作:命令写⼊(append)、⽂件同步(sync)、⽂件重写(rewrite)、重启加载(load),如图所⽰。
  1. 所有的写⼊命令会追加到 aof_buf(缓冲区)中。
  2. AOF 缓冲区根据对应的策略向硬盘做同步操作。
  3. 随着 AOF ⽂件越来越⼤,需要定期对 AOF ⽂件进⾏重写,达到压缩的⽬的。
  4. 当 Redis 服务器启动时,可以加载 AOF ⽂件进⾏数据恢复。

命令写入

AOF 命令写⼊的内容直接是⽂本协议格式。例如 set hello world 这条命令,在 AOF 缓冲区会追加如下⽂本:
*3\r\n$3\r\nset\r\n$5\r\nhello\r\n$5\r\nworld\r\n
此处遵守 Redis 格式协议,Redis 选择⽂本协议可能的原因:⽂本协议具备较好的兼容性;实现简单;具备可读性。
AOF 过程中为什么需要 aof_buf 这个缓冲区?Redis 使⽤单线程响应命令,如果每次写 AOF ⽂件都直接同步硬盘,性能从内存的读写变成 IO 读写,必然会下降。先写⼊缓冲区可以有效减少 IO 次数,同时,Redis 还可以提供多种缓冲区同步策略,让⽤⼾根据⾃⼰的需求做出合理的平衡。

文件同步

Redis 提供了多种 AOF 缓冲区同步⽂件策略,由参数 appendfsync 控制,不同值的含义如下表所⽰。
可配置值
说明
always
命令写⼊ aof_buf 后调⽤ fsync 同步,完成后返回
everysec
命令写⼊aof_buf 后只执⾏ write 操作,不进⾏ fsync。每秒由同步线程进⾏ fsync。
no
命令写⼊ aof_buf 后只执⾏ write 操作,由 OS 控制 fsync 频率。
系统调⽤ write 和 fsync 说明:
  • write 操作会触发延迟写(delayed write)机制。Linux 在内核提供⻚缓冲区⽤来提供硬盘 IO 性能。write 操作在写⼊系统缓冲区后⽴即返回。同步硬盘操作依赖于系统调度机制,例如:缓冲区⻚空间写满或达到特定时间周期。同步⽂件之前,如果此时系统故障宕机,缓冲区内数据将丢失。
  • Fsync 针对单个⽂件操作,做强制硬盘同步,fsync 将阻塞直到数据写⼊到硬盘。
  • 配置为 always 时,每次写⼊都要同步 AOF ⽂件,性能很差,在⼀般的 SATA 硬盘上,只能⽀持⼤约⼏百 TPS 写⼊。除⾮是⾮常重要的数据,否则不建议配置。
  • 配置为 no 时,由于操作系统同步策略不可控,虽然提⾼了性能,但数据丢失⻛险⼤增,除⾮数据重要程度很低,⼀般不建议配置。
  • 配置为 everysec,是默认配置,也是推荐配置,兼顾了数据安全性和性能。理论上最多丢失 1 秒的数据。

重写机制

随着命令不断写⼊ AOF,⽂件会越来越⼤,为了解决这个问题,Redis 引⼊ AOF 重写机制压缩⽂
件体积。AOF ⽂件重写是把 Redis 进程内的数据转化为写命令同步到新的 AOF ⽂件。
重写后的 AOF 为什么可以变⼩?有如下原因:
  • 进程内已超时的数据不再写⼊⽂件。
  • 旧的 AOF 中的⽆效命令,例如 del、hdel 等重写后将会删除,只需要保留数据的最终版本。
  • 多条写操作合并为⼀条,例如 lpush list a、lpush list b、lpush list 从可以合并为 lpush list a b c。
较⼩的 AOF ⽂件⼀⽅⾯降低了硬盘空间占⽤,⼀⽅⾯可以提升启动 Redis 时数据恢复的速度。 AOF 重写过程可以⼿动触发和⾃动触发:
  • ⼿动触发:调⽤ bgrewriteaof 命令。
  • ⾃动触发:根据 auto-aof-rewrite-min-size 和 auto-aof-rewrite-percentage 参数确定⾃动触发时机。auto-aof-rewrite-min-size:表⽰触发重写时 AOF 的最小⽂件⼤小,默认为 64MB。auto-aof-rewrite-percentage:代表当前 AOF 占⽤⼤小相⽐较上次重写时增加的⽐例。
当触发 AOF 重写时,图 4-3 介绍它的运⾏流程。
1. 执⾏ AOF 重写请求。
如果当前进程正在执⾏ AOF 重写,请求不执⾏。如果当前进程正在执⾏ bgsave 操作,重写命令
延迟到 bgsave 完成之后再执⾏。
2. ⽗进程执⾏ fork 创建⼦进程。
3. 重写
  • 主进程 fork 之后,继续响应其他命令。所有修改操作写⼊ AOF 缓冲区并根据 appendfsync 策略同步到硬盘,保证旧 AOF ⽂件机制正确。
  • ⼦进程只有 fork 之前的所有内存信息,⽗进程中需要将 fork 之后这段时间的修改操作写⼊aof_rewrite_buf 重写缓冲区中。
4. ⼦进程根据内存快照,将命令合并到新的 AOF ⽂件中。
5. ⼦进程完成重写
  • 新⽂件写⼊后,⼦进程发送信号给⽗进程。
  • ⽗进程把 AOF重写缓冲区内临时保存的命令追加到新 AOF ⽂件中。
  • ⽤新 AOF ⽂件替换老 AOF ⽂件。

AOF 的优缺点

AOF 的优点

  • 数据安全性高:AOF 通过记录每次写操作的命令,能够提供更接近实时的数据持久化。即使 Redis 服务器崩溃,也可以通过 AOF 文件恢复数据。

  • 可读性强:AOF 文件是纯文本格式,记录的是 Redis 的命令。这意味着你可以手动编辑 AOF 文件,例如在文件末尾删除一些错误的命令。

  • 数据恢复简单:重启 Redis 时,只需重新执行 AOF 文件中的命令即可恢复数据,过程简单且可靠。

AOF 的缺点

  • 文件体积可能较大:AOF 文件记录了每次写操作的命令,因此文件体积可能会比 RDB 文件大得多。不过,通过 AOF 重写机制可以有效控制文件大小。

  • 恢复速度较慢:由于 AOF 文件需要逐条执行命令来恢复数据,因此恢复速度可能比 RDB 恢复慢,尤其是在数据量较大的情况下。

  • 性能开销:如果选择 appendfsync always,每次写操作都会同步到磁盘,可能会对性能产生较大影响。

AOF 与 RDB 的对比

数据安全性

  • RDB:"定期",数据安全性较低。由于 RDB 是基于时间间隔的快照,可能会丢失最后一次快照之后的数据。

  • AOF:"实时",数据安全性较高。AOF 通过记录每次写操作的命令,可以配置不同的同步策略(如每秒同步一次或每次写操作都同步),从而最大限度地减少数据丢失的风险。

性能表现

  • RDB:性能较好。RDB 是通过子进程异步生成快照,对主线程的性能影响较小。恢复数据时,RDB 文件是二进制格式,加载速度较快。

  • AOF:性能可能受到同步策略的影响。如果配置为每次写操作都同步到磁盘(appendfsync always),性能开销较大;如果配置为每秒同步一次(appendfsync everysec),性能影响较小。

文件大小

  • RDB:文件体积较小,因为它是数据的压缩二进制快照。

  • AOF:文件体积通常较大,因为记录了每次写操作的命令。不过,AOF 支持重写机制,可以通过优化命令集来减少文件大小。

恢复速度

  • RDB:恢复速度较快,因为它直接加载二进制文件。

  • AOF:恢复速度较慢,因为需要逐条执行 AOF 文件中的命令来重建数据。

混合使用

Redis 允许同时启用 RDB 和 AOF 持久化机制,结合两者的优点:

  • RDB 提供快速恢复和备份能力。

  • AOF 提供更高的数据安全性。

这时就需要开启使用 aof 文件,在配置文件 /etc/redis/redis.conf 中设置配置:appendonly yes。之后在使用 redis 客户端时需要手动触发生成 aof 文件,即保存完数据都需要使用 bgrewriteaof 命令,这时候生成的 aof 文件的内容为二进制,即 rdb 文件的内容,这样就能结合两种的优点。

例如,保存如下几个数据,并使用 bgrewriteaof 命令手动生成的 aof 文件

这时我们查看 aof 文件的内容均为二进制


网站公告

今日签到

点亮在社区的每一天
去签到