Redis 持久化

2024-01-13 09:53:31 浏览数 (2)

Redis 提供了两种持久化方式,即 RDB(Redis Database)和 AOF(Append-Only File)。

RDB

RDB 持久化是 Redis 的默认持久化方式。它将 Redis 的数据集以二进制格式保存到磁盘上的一个文件中。RDB 持久化适用于执行周期性备份的场景。RDB 文件是通过压缩(可以配置 rdbcompression 参数禁用压缩以节省 CPU 资源)的二进制格式,更加紧凑以节省空间。

  • 触发机制:管理员可以根据配置文件设置触发 RDB 持久化的方式,例如在指定的时间间隔内、在指定的修改次数后、或同时满足时间和修改次数的条件下触发。
  • 优点:RDB 持久化对性能影响较小,生成的 RDB 文件紧凑且易于备份和恢复。
  • 缺点:RDB 持久化会将数据保存到一个快照文件中,因此在发生故障时可能会丢失最后一次快照之后的数据。
快照原理

Redis 会默认将备份的快照文件存储在 Redis 当前进程工作目录中的 dump.rbd 文件中,可以配置 dir 和 dirfilename 两个参数分别指定快照的存储路径和文件名。

创建快照的步骤:

  1. fork 复制当前 redis 进程的一个副本
  2. 父进程继续接受客户端的请求并处理,子进程开始将内存中的数据写入硬盘中的临时文件
  3. 写入完毕,会使用临时文件替换目录下的 RDB 文件

在执行 fork 函数时,类 unix 操作系统会使用写时拷贝策略。所以新的 RDB 文件存储的时执行 fork 函数那一刻的内存数据。 关于写时拷贝(Copy-On-Write,COW) 在使用写时拷贝的情况下,当多个进程或线程共享同一份内存数据时,它们实际上共享同一个物理内存页。这意味着在一开始,这些进程或线程都指向相同的内存页。当其中一个进程或线程尝试修改这个共享的内存页时,才会进行实际的拷贝操作。这个操作会将要修改的内存页复制一份,使得修改操作只影响到修改操作的那个进程或线程,而不会影响其他共享该内存页的进程或线程。 写时拷贝的优点是在数据没有发生写操作之前,多个进程或线程可以共享同一份内存数据,避免了不必要的内存复制。这对于需要共享大量数据或频繁进行复制操作的情况下,可以提高性能和节省内存空间。

自动快照机制

在 Redis 中,可以通过在配置文件中设置 save指令来配置自动触发快照的规则。save指令的格式如下:

代码语言:javascript复制
save <seconds> <changes>

其中,<seconds>表示时间间隔,单位是秒,指定了多长时间内如果发生了至少 <changes> 次修改操作,则触发快照。

例如,以下是一些示例配置规则:

代码语言:javascript复制
save 900 1       # 如果在900秒(15分钟)内至少有1个键被修改,则触发快照
save 60 10000    # 如果在60秒内至少有10000个键被修改,则触发快照
save 300 5       # 如果在300秒(5分钟)内至少有5个键被修改,则触发快照

在上述示例中,Redis 会根据指定的时间间隔和修改次数来判断是否触发快照生成。当满足任意一个配置规则时,Redis 将自动执行快照操作。

需要注意的是,配置多个 save指令会形成一个规则列表。当 Redis 执行快照时,会按照规则列表的顺序进行判断。因此,应该将频率较低、更保守的规则放在列表的前面,而将频率较高、更宽松的规则放在列表的后面。

手动快照机制
SAVE

当执行 SAVE命令时,Redis 会阻塞主进程,将数据集以二进制格式保存到磁盘上的一个 RDB 文件中。在生成快照期间,Redis 不能处理其他命令请求,直到快照过程完成。

SAVE命令在快照生成期间对 Redis 的性能会有一定的影响,因此,不建议在生产环境中使用 SAVE,一般情况下建议使用 BGSAVE命令进行快照生成。

BGSAVE

BGSAVE命令用于在后台异步执行生成 Redis 快照。当执行 BGSAVE命令时,Redis 会启动一个子进程来生成快照,而不会阻塞主进程。在子进程生成快照的同时,Redis 主进程可以继续处理其他命令请求。

LASTSAVE命令用于获取最后一次生成快照的时间戳。执行 LASTSAVE命令后,Redis 会返回一个表示最后一次生成快照时间的 UNIX 时间戳。

FLUSHALL

执行 FLUSHALL命令将删除当前正在使用的所有数据库中的所有键值对。这个命令会导致所有数据被永久删除。FLUSHALL命令是一个原子操作,即要么全部清空成功,要么全部失败。在执行期间,Redis 将阻塞其他命令的执行。

如果当前配置了自动快照条件,那么不论清空过程是否达到快照条件,都会进行快照。

主从模式下的复制

关于主从模式和复制的内容应该单独讲,所以这里就不讨论了

AOF

AOF 持久化以日志的形式记录 Redis 服务器所执行的写操作,将这些写操作追加到文件的末尾。当 Redis 重新启动时,可以通过重新执行这些写操作来还原数据集。在配置文件中找到 appendonly 的配置项,配置 appendonly yes 启用配置。

  • 触发机制:管理员可以根据配置文件设置 AOF 持久化的触发方式,例如每次写操作、每秒同步等。
  • 优点:AOF 持久化提供了更高的数据安全性,因为可以通过重放 AOF 日志来恢复数据。此外,AOF 文件是可读的,可以用于故障排查和数据分析。
  • 缺点:相比 RDB 持久化,AOF 持久化文件更大,恢复速度可能较慢,对于大的写操作负载可能会影响性能。
AOF 的实现

AOF 文件是一个文本文件,其中包含了 Redis 接收到的每个写操作的命令。每个命令都以 Redis 协议格式进行编码,并追加到 AOF 文件的末尾。

下面是一个示例,展示了在 AOF 文件中可能包含的命令:

代码语言:javascript复制
*3rn$3rnSETrn$5rnmykeyrn$7rnmyvaluern
*2rn$3rnGETrn$5rnmykeyrn
*4rn$4rnHMSETrn$6rnmyhashrn$2rna1rn$3rnvalrn$2rna2rn$3rn123rn

每个命令由多个部分组成,以 rn(CRLF)作为分隔符。以下是命令的结构:

  • *3rn:表示命令由三个参数组成。
  • $3rnSETrn:表示第一个参数是字符串,长度为 3,值为”SET”。
  • $5rnmykeyrn:表示第二个参数是字符串,长度为 5,值为”mykey”。
  • $7rnmyvaluern:表示第三个参数是字符串,长度为 7,值为”myvalue”。

在 AOF 文件中,每个命令都按照此格式(redis 的通信协议格式)记录。当 Redis 重新启动时,它会逐行读取 AOF 文件中的命令,并将其重新执行,以还原数据。

需要注意的是,AOF 文件是追加写入的,因此它会随着每个新的写操作而增长。为了保护数据的完整性,可以根据需要选择合适的 AOF 同步策略,确保将写操作同步到磁盘。

AOF 的优化

如果有这样三条命令,实际上对于恢复数据来讲,前两条记录是无用的。随着执行的命令越来越多,AOF 文件也越来越大,即使内存中的数据可能并不多。

代码语言:javascript复制
SET key 1
SET key 2
SET key 3

redis 能够自动优化 AOF 文件,每当达到一定条件 redis 就会重写 AOF 文件,这个条件可以在配置文件中配置:

代码语言:javascript复制
1、auto-aof-rewrite-percentage:该配置项表示当AOF文件的大小超过上一次AOF重写(如果没有重写则以启动时大小为标准)之后的大小的一定百分比时,Redis会自动触发AOF重写。默认值为100,即AOF文件大小超过上一次重写大小的100%时触发重写。

2、auto-aof-rewrite-min-size:该配置项表示当AOF文件的大小超过一定字节数时,Redis会自动触发AOF重写,无论是否超过了上一次AOF重写之后的大小。默认值为64MB。

AOF 重写通过读取当前数据集的内存状态,并以更紧凑的方式重新写入 AOF 文件,去除了冗余的命令和操作。AOF 重写不会影响正在运行的 Redis 实例的正常操作,它是在后台进行的。

AOF 重写的过程如下:

  • Redis 会创建一个后台进程,该进程负责扫描当前数据集的所有写操作,并生成一个新的 AOF 文件。
  • 在生成新的 AOF 文件时,只记录了重写期间的写操作,不包括旧 AOF 文件中的命令。
  • 重写完成后,Redis 会用新的 AOF 文件替换旧的 AOF 文件。
硬盘同步

事实上,由于 IO 缓存机制,进程的 IO 操作并不会立马体现在磁盘内容上。操作系统会将 IO 操作中的数据暂时存储在内存中的缓存中,并在适当的时机将其刷新到磁盘上。IO 缓存的存在可以提高 IO 性能,因为内存中的读取和写入比磁盘访问要快得多。通过将多个 IO 操作合并成更大的块,可以减少磁盘访问的次数,从而提高效率。这种方式下,进程可以更快地完成 IO 操作并继续执行后续的任务。

然而,IO 缓存也引入了数据持久性和一致性的问题。如果系统发生故障(如断电),尚未刷新到磁盘的缓存数据可能会丢失。这种情况造成的损失对于使用 redis 写入 AOF 文件实现持久化的应用时无法容忍的,这就需要 redis 再写入 AOF 文件后立即将缓存同步到磁盘中。

在 redis 中, appendfsync配置项用于控制 AOF(Append-Only File)文件的同步策略,即何时将 AOF 缓冲区的数据同步到磁盘。

在配置文件中,有三个可选的 appendfsync选项:

  1. appendfsync always:表示每次执行写操作时都会将 AOF 缓冲区的数据立即同步到磁盘。这是最安全的选项,因为它可以确保每个写操作都持久化到磁盘,但也会对性能产生较大的影响,因为每次写操作都需要等待磁盘的响应。
  2. appendfsync everysec:表示每秒将 AOF 缓冲区的数据同步到磁盘一次。这是默认的选项,它在性能和数据安全之间取得了一种平衡。Redis 会将 AOF 缓冲区的数据积累到一定程度,然后每秒同步一次到磁盘,这样可以提高性能并保证一定程度的数据持久化。
  3. appendfsync no:表示完全依赖操作系统进行数据同步,即不强制要求将 AOF 缓冲区的数据立即同步到磁盘。这是最高性能的选项,因为写操作不会等待磁盘的响应,但也是最不安全的选项,因为在发生系统崩溃等情况时可能会导致数据丢失。

操作系统提供了同步写(synchronous write)和异步写(asynchronous write)两种方式。

  • 同步写(Synchronous Write):在同步写模式下,每次 IO 操作完成后,操作系统会立即将数据写入磁盘并进行同步操作,确保数据的持久性和一致性。这意味着写操作会阻塞,直到数据被写入磁盘为止,但可以提供更高的数据可靠性。
  • 异步写(Asynchronous Write):在异步写模式下,操作系统会将数据写入磁盘的操作交给后台线程或其他机制处理,而不会阻塞进程的执行。这样可以提高 IO 操作的性能,但也会增加数据丢失的风险,因为在数据被刷新到磁盘之前发生故障,尚未写入磁盘的数据可能会丢失。

因此,在涉及到数据持久性和一致性的场景中,可以根据需求选择合适的同步或异步写模式,以平衡性能和数据可靠性的需求。

混合持久化

可以同时使用 RDB 和 AOF 来进行持久化。

同时启用 RDB 和 AOF,Redis 可以将数据保存到磁盘上的两个不同文件中。RDB 会定期创建快照,将内存中的数据保存到磁盘上的 RDB 文件中,而 AOF 会记录每个写操作的指令,将其追加到 AOF 文件中。

同时使用 RDB 和 AOF 的好处包括:

  • 数据安全性:RDB 和 AOF 都提供了数据持久化的机制,可以将数据写入磁盘以保证数据的安全性。如果其中一种持久化方式发生故障,另一种方式仍然可以用于恢复数据。
  • 灵活的恢复选项:使用混合持久化可以根据需要选择不同的恢复策略。RDB 快照适用于快速恢复,因为它可以在较短的时间内加载大量的数据。而 AOF 文件记录了写操作的历史记录,可以提供更精确的恢复点。
  • 性能优化:RDB 快照对于大规模的数据恢复来说效率更高,而 AOF 文件对于重放操作日志来说更高效。通过同时使用 RDB 和 AOF,可以根据应用程序的需求进行性能优化。

------本页内容已结束,喜欢请分享------


0 人点赞