Redis 持久化机制
RDB 持久化
Redis RDB(Redis DataBase)是Redis的一种持久化方式。它可以将Redis中的数据快照存储在硬盘上,并在需要时重构该数据快照。因为可以在磁盘上存储和重构数据快照,所以RDB是一种非常高效的Redis数据备份和恢复方式。具有灵活性和高效性的RDB在实际应用中被广泛使用。
RDB的工作原理是当Redis满足一定条件时,Redis会将数据写入到一个RDB文件中。这些条件通常是:
- 指定的时间间隔内发生了指定数量的写操作,例如10000个键被修改等。
- 指定的时间间隔内有指定数量的写操作,例如至少有5个键被修改,且至少过去了半小时等。
在创建RDB文件时,Redis会执行一个fork操作,它在Redis内部创建了一个子进程来执行实际的RDB文件生成工作。父进程继续处理客户端请求,而子进程则负责将数据写入到RDB文件中。由于使用了fork,所以这个过程是非常快速和效率的。
RDB文件是一个二进制文件,可以通过指定的配置选项控制其生成频率和命名规则。在需要恢复Redis数据时,可以使用RDB文件进行恢复。同时,Redis还支持AOF(Append Only File)持久化方式,它可以将每个Redis命令的执行记录写入到一个日志文件中,并在需要时回放这些命令来恢复数据。相比之下,RDB方式更加简单,且恢复速度更快。
Redis 提供了两个命令来生成 RDB 快照文件
-
save : 同步保存操作,会阻塞 Redis 主线程;
-
bgsave : fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项。
RDB 是默认的持久化方式吗?默认开启吗?如何设置?
RDB是Redis的默认持久化方式,并且在默认情况下开启。但是,您可以通过修改Redis的配置文件来启用或禁用RDB持久化,或者更改持久化频率和命名规则等参数。
以下是设置RDB持久化的示例代码:
# 启用RDB方式持久化
save 900 1 # 如果在900秒内,有至少1个键被修改,就执行持久化操作
save 300 10 # 如果在300秒内,有至少10个键被修改,就执行持久化操作
save 60 10000 # 如果在60秒内,有至少10000个键被修改,就执行持久化操作
# 禁用RDB方式持久化
# save ""
在这个示例中,我们通过修改配置文件中的 save
参数来调整RDB持久化的频率,它定义了在一定时间内,有多少个键被修改时需要执行持久化操作。在本例中,如果在900秒内至少有1个键被修改,则执行持久化操作,并将数据快照存储在硬盘上。在Redis中,每个持久化规则单独占一行,根据实际情况设置即可。
如果您想完全禁用RDB持久化,可以将所有 save
规则删掉,或者将它们全部注释掉。另外,您也可以通过在Redis的配置文件中设置 save ""
来禁用RDB持久化。
总之,Redis RDB持久化方式提供了非常有效的Redis数据备份和恢复方式,并且默认情况下已经开启。使用上面的示例代码,您可以轻松地更改RDB持久化的频率和规则,以满足您的实际需求。
AOF 持久化
与快照持久化相比,AOF 持久化的实时性更好。默认情况下 Redis 没有开启 AOF(append only file)方式的持久化(Redis 6.0 之后已经默认是开启了),可以通过 appendonly 参数开启:
appendonly yes
开启 AOF 持久化后每执行一条会更改 Redis 中的数据的命令,Redis 就会将该命令写入到 AOF 缓冲区 server.aof_buf 中,然后再写入到 AOF 文件中(此时还在系统内核缓存区未同步到磁盘),最后再根据持久化方式( fsync策略)的配置来决定何时将系统内核缓存区的数据同步到硬盘中的。
只有同步到磁盘中才算持久化保存了,否则依然存在数据丢失的风险,比如说:系统内核缓存区的数据还未同步,磁盘机器就宕机了,那这部分数据就算丢失了。AOF 文件的保存位置和 RDB 文件的位置相同,都是通过 dir 参数设置的,默认的文件名是 appendonly.aof。
AOF持久化配置与RDB类似,可以通过Redis配置文件进行设置,常见的配置方式有:
- APPENDONLY yes:启用AOF持久化方式。
- appendfsync always:每次写入都会立即将数据同步到硬盘,这是最安全的配置。
- appendfsync everysec:每秒钟将数据同步一次到硬盘。
- appendfsync no:数据异步写入磁盘,每次之间的数据可能会有一定的数据丢失风险。但性能也是最好的。
以下是通过Redis命令行设置AOF持久化的示例代码:
# 启用AOF持久化并将数据同步到硬盘
CONFIG SET appendonly yes
CONFIG SET appendfsync always
在这个示例中,我们使用 CONFIG SET
命令来修改Redis的配置并设置AOF持久化方式。启用AOF方式后,Redis会在每个写命令执行时将其写入一个AOF文件,并使用指定的 appendfsync
配置将数据同步到硬盘。
在实际应用中,AOF方式被广泛使用,并且可以与RDB持久化方式配合使用,以实现多层数据备份和恢复。使用AOF方式,可以更好地保护Redis数据不丢失,以及提高整个系统的可靠性。
AOF 工作基本流程
AOF 持久化功能的实现可以简单分为 5 步:
-
命令追加(append):所有的写命令会追加到 AOF 缓冲区中。
-
文件写入(write):将 AOF 缓冲区的数据写入到 AOF 文件中。这一步需要调用write函数(系统调用),write将数据写入到了系统内核缓冲区之后直接返回了(延迟写)。注意!!!此时并没有同步到磁盘。
-
文件同步(fsync):AOF 缓冲区根据对应的持久化方式( fsync 策略)向硬盘做同步操作。这一步需要调用 fsync 函数(系统调用), fsync 针对单个文件操作,对其进行强制硬盘同步,fsync 将阻塞直到写入磁盘完成后返回,保证了数据持久化。
-
文件重写(rewrite):随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
-
重启加载(load):当 Redis 重启时,可以加载 AOF 文件进行数据恢复。
这里对上面提到的一些 Linux 系统调用再做一遍解释:
write:写入系统内核缓冲区之后直接返回(仅仅是写到缓冲区),不会立即同步到硬盘。虽然提高了效率,但也带来了数据丢失的风险。
同步硬盘操作通常依赖于系统调度机制,Linux 内核通常为 30s 同步一次,具体值取决于写出的数据量和 I/O 缓冲区的状态。
fsync:fsync用于强制刷新系统内核缓冲区(同步到到磁盘),确保写磁盘操作结束才会返回。
内核缓冲区
内核缓冲区(Kernel Buffer)是操作系统内核为了提高磁盘 I/O 性能而设置的一种缓存区域,作为用户进程和磁盘之间的缓冲区。当用户进程执行文件写操作时,数据先被拷贝到内核缓冲区中,然后再由内核将其写入磁盘。内核缓冲区可以减少磁盘 I/O 操作的次数和时间,达到提高写性能的目的。
在Redis的AOF持久化过程中,内核缓冲区也扮演着非常重要的角色。Redis通过调用系统调用write将AOF缓冲区中的数据写入内核缓冲区,并返回给Redis进程。这样做有助于减少Redis进程对磁盘的访问次数,提高写入性能。
然而,这种做法也有一定的风险。如果系统在写入内核缓冲区后发生崩溃或断电等情况,内核缓冲区中的数据可能会丢失。为了避免这种情况,Redis在写入内核缓冲区后,还需要调用系统调用fsync将内核缓冲区中的数据写入磁盘中,并通过强制同步的方式保证数据的可靠性和持久化。
综上所述,内核缓冲区是提高磁盘 I/O 性能的关键因素之一,但同时也需要注意数据的安全性。在Redis的AOF持久化中,需要注意平衡写入性能和数据安全性之间的关系,以便为应用程序提供最高效的永久存储方式。
AOF 持久化策略
在 Redis 的配置文件中存在三种不同的 AOF 持久化方式( fsync策略),它们分别是:
-
appendfsync always:主线程调用 write 执行写操作后,后台线程( aof_fsync 线程)立即会调用 fsync 函数同步 AOF 文件(刷盘),fsync 完成后线程返回,这样会严重降低 Redis 的性能(write + fsync)。
-
appendfsync everysec:主线程调用 write 执行写操作后立即返回,由后台线程( aof_fsync 线程)每秒钟调用 fsync 函数(系统调用)同步一次 AOF 文件(write+fsync,fsync间隔为 1 秒)
-
appendfsync no:主线程调用 write 执行写操作后立即返回,让操作系统决定何时进行同步,Linux 下一般为 30 秒一次(write但不fsync,fsync 的时机由操作系统决定)。
可以看出:这 3 种持久化方式的主要区别在于 fsync 同步 AOF 文件的时机(刷盘)。
为了兼顾数据和写入性能,可以考虑 appendfsync everysec 选项 ,让 Redis 每秒同步一次 AOF 文件,Redis 性能受到的影响较小。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,Redis 还会优雅的放慢自己的速度以便适应硬盘的最大写入速度。
从 Redis 7.0.0 开始,Redis 使用了 Multi Part AOF 机制。顾名思义,Multi Part AOF 就是将原来的单个 AOF 文件拆分成多个 AOF 文件。在 Multi Part AOF 中,AOF 文件被分为三种类型,分别为:BASE:表示基础 AOF 文件,它一般由子进程通过重写产生,该文件最多只有一个。INCR:表示增量 AOF 文件,它一般会在 AOFRW 开始执行时被创建,该文件可能存在多个。HISTORY:表示历史 AOF 文件,它由 BASE 和 INCR AOF 变化而来,每次 AOFRW 成功完成时,本次 AOFRW 之前对应的 BASE 和 INCR AOF 都将变为 HISTORY,HISTORY 类型的 AOF 会被 Redis 自动删除。