Logo
Section 1 / 6

Redis:持久化

让我们讨论一下 Redis 如何将数据存储在硬盘上。

导入

Redis:持久化

让我们讨论一下 Redis 如何将数据存储在硬盘上。

Redis 是一个内存数据库,意味着数据存储在内存(RAM)中。当服务器发生崩溃时,存储在内存中的所有数据都会丢失。为了防止这种情况,Redis 提供了将数据备份到磁盘的机制。在发生故障时,服务器重启后可以从磁盘加载数据到内存。

Redis 提供两种持久化选项,我们将在下面进行讨论:

RDB 持久化(快照)

在 RDB(Redis 数据库)持久化中,数据的快照会被保存到磁盘上的 dump.rdb 文件中。快照的时间间隔由配置文件定义。redis.conf 文件中默认的配置如下:

1save 900 1 2save 300 10 3save 60 10000

上述示例中,数据保存的行为如下:

  • 900 秒(15 分钟)后,如果至少有 1 个键发生变化;
  • 300 秒(5 分钟)后,如果至少有 10 个键发生变化;
  • 60 秒后,如果至少有 10000 个键发生变化。

如果负载较高且数据写入频繁,Redis 将每分钟进行一次备份;如果负载中等,则每五分钟备份一次,依此类推。

数据的持久性取决于数据写入磁盘的频率。如果每五分钟备份一次,而服务器在上次备份后的几分钟内崩溃,那么最近四分钟内的数据就会丢失。因此,备份周期需要仔细权衡。

用户也可以使用 SAVE 命令手动将数据保存到 RDB 文件中。但该命令会阻塞 Redis 服务器,应避免使用。推荐使用 BGSAVE 命令,它通过创建子进程来完成快照,不会阻塞主进程。

可以通过删除 redis.conf 文件中的所有 save 指令并重启 Redis 服务器来禁用快照功能。

RDB 的配置选项

redis.conf 文件中提供了一些用于配置数据持久化的指令,以下是其中几个重要选项:

  1. rdbcompression:若此指令值为 true,Redis 会使用 LZF 压缩算法。默认值为 true。如果希望节省子进程的 CPU 开销,可将其设为 false。
  2. rdbchecksum:若值为 yes,会在 RDB 文件末尾添加 CRC64 校验和,提高文件抗损坏能力。但会带来约 10% 的性能损耗(保存和加载时),若追求极致性能,可关闭此项。禁用校验和的 RDB 文件其校验和为零,加载时会跳过校验。
  3. stop-writes-on-bgsave-error:若启用此选项,当最近一次后台保存失败时,Redis 将停止接受写操作。一旦后台保存恢复,Redis 会自动重新允许写入。默认值为 true。不建议将其改为 false,因为若磁盘保存出现问题,用户应能及时察觉。
  4. dbfilename:用于指定 RDB 文件的名称,默认为 dump.rdb。

快照对性能的影响

Redis 会创建一个子进程将数据写入磁盘。如果在子进程写入过程中有数据被修改,子进程也需要复制这部分数据,这可能耗时较长。当数据集较大时,可能导致 Redis 暂停服务数毫秒到一秒钟。相比之下,接下来要介绍的 AOF 方法在性能方面表现更优。

仅追加文件(AOF)持久化

当启用 AOF 时,服务器接收到的每个写操作都会被记录到一个日志文件中。当 Redis 重启时,会重新执行 AOF 文件中的所有命令,从而重建完整的数据集。

随着时间推移,AOF 文件可能变得非常大,因为它记录了每个键的所有历史操作。为解决这个问题,Redis 会定期重写 AOF 文件,使其尽可能小。重写后,不再保存完整的历史记录,而是从某个键的最新状态开始记录。

例如,假设我们在 Redis 中设置键 count 初始值为 1,并多次通过 set 命令修改它。AOF 文件内容可能如下:

1set count 1 2set count 4 3set count 12 4set count 56

当 Redis 重写该文件时,只需保留最后一条命令即可,其余命令均无必要:

1set count 56

我们可以根据当前 AOF 文件大小以及自上次重写以来允许的增长百分比来配置重写频率。

尽管 Redis 会立即发送新命令追加到文件中,但操作系统通常会将这些命令暂存于缓冲区,并每隔若干秒才刷新到磁盘。这意味着如果在缓冲区中的命令尚未写入磁盘时发生断电,可能会丢失部分数据。为避免这种情况,Redis 默认每秒强制刷新一次缓冲区。我们也可以配置为每次命令都强制刷新,但这会使每个命令的响应速度显著变慢。

AOF 的配置选项

  1. appendonly:用于启用 AOF 功能。默认值为 false。要启用 AOF,请将其设为 true 并重启服务器。
  2. appendfilename:指定 AOF 文件的名称,默认为 appendonly.aof。
  3. appendfsync:操作系统中存在 fsync() 系统调用,用于将缓冲区数据强制写入磁盘。该操作可以每秒或每十秒执行一次,具体由操作系统决定。Redis 可通过 appendfsync 指令控制这一行为,有三个选项:
    • no:由操作系统决定何时刷新;
    • always:每次写操作都立即刷新,最安全但性能最差;
    • everysec:每秒刷新一次。
  4. no-appendfsync-on-rewrite:当 AOF 的同步策略设置为 always 或 everysec,且后台保存进程正在大量进行磁盘 I/O 时,Redis 主进程的 fsync() 调用可能被长时间阻塞。若启用此选项,当 BGSAVE 或 BGREWRITEAOF 正在运行时,主进程将不会执行 fsync()。这意味着在此期间,Redis 的持久性等同于 appendfsync no。
  5. auto-aof-rewrite-percentage:指定自动重写 AOF 文件的触发条件。例如,若该值为 20,当 AOF 文件大小比上次重写后增长 20% 时,Redis 会自动执行 BGREWRITEAOF 命令。默认值为 100。
  6. auto-aof-rewrite-min-size:AOF 文件重写的最小尺寸。即使达到 auto-aof-rewrite-percentage 的阈值,只有当 AOF 文件大小达到此最小值时才会触发重写。默认值为 67,108,864 字节(约 64MB)。

应该选择哪种持久化策略?

Redis 默认采用快照(RDB)作为持久化策略。如果你可以接受最多丢失几秒钟的数据,那么使用 RDB 即可。如果你要求完全的数据持久性,不能容忍任何数据丢失,则应使用 AOF。你也可以同时启用两种策略,但 Redis 在恢复数据时会优先使用 AOF,因为它记录的信息最完整、最准确。

Redis 命令

Redis:复制