Redis 持久化策略及其优缺点

原文:Redis 有哪 2 种持久化方式?分别的优缺点是什么?,补充了 Redis 持久化配置

Redis 的读写操作都是在内存中,所以 Redis 性能才会高,但是当 Redis 重启后,内存中的数据就会丢失,那为了保证内存中的数据不会丢失,Redis 实现了数据持久化的机制,这个机制会把数据存储到磁盘,这样在 Redis 重启就能够从磁盘中恢复原有的数据。Redis 共有两种数据持久化的方式:

  • AOF(Append Only File):每执行一条写操作命令,就把该命令以追加的方式写入到一个文件里(保存日志);
  • RDB(Redis Database):将某一时刻的内存数据,以二进制的方式写入磁盘(保存快照)。

AOF 日志是如何实现的?

Redis 在执行完一条写操作命令后,就会把该命令以追加的方式写入到一个文件里,然后 Redis 重启时,会读取该文件记录的命令,然后逐一执行命令的方式来进行数据恢复。

img

我这里以「set name xiaolin」命令作为例子,Redis 执行了这条命令后,记录在 AOF 日志里的内容如下图:

img

Redis 提供了 3 种写回硬盘的策略,在 Redis.conf 配置文件中的 appendfsync 配置项可以有以下 3 种参数可填:

  • Always,总是,每次写操作命令执行完后,同步将 AOF 日志数据写回硬盘;
  • Everysec,每秒,每次写操作命令执行完后,先将命令写入到 AOF 文件的内核缓冲区,然后每隔一秒将缓冲区里的内容写回到硬盘;
  • No,意味着不由 Redis 控制写回硬盘的时机,转交给操作系统控制写回的时机,也就是每次写操作命令执行完后,先将命令写入到 AOF 文件的内核缓冲区,再由操作系统决定何时将缓冲区内容写回硬盘。

我也把这 3 个写回策略的优缺点总结成了一张表格:

img

RDB 快照是如何实现的呢?

因为 AOF 日志记录的是操作命令,不是实际的数据,所以用 AOF 方法做故障恢复时,需要全量把日志都执行一遍,一旦 AOF 日志非常多,势必会造成 Redis 的恢复操作缓慢。为了解决这个问题,Redis 增加了 RDB 快照。

所谓的快照,就是记录某一个瞬间东西,比如当我们给风景拍照时,那一个瞬间的画面和信息就记录到了一张照片。所以,RDB 快照就是记录某一个瞬间的内存数据,记录的是实际数据,而 AOF 文件记录的是命令操作的日志,而不是实际的数据。因此在 Redis 恢复数据时,RDB 恢复数据的效率会比 AOF 高些,因为直接将 RDB 文件读入内存就可以,不需要像 AOF 那样还需要额外执行操作命令的步骤才能恢复数据。

Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave,他们的区别就在于是否在「主线程」里执行:

  • 执行了 save 命令,就会在主线程生成 RDB 文件,由于和执行操作命令在同一个线程,所以如果写入 RDB 文件的时间太长,会阻塞主线程;
  • 执行了 bgsave 命令,会创建一个子进程来生成 RDB 文件,这样可以避免主线程的阻塞;

AOF 和 RDB 优缺点

AOF:

  • 优点:首先,AOF 提供了更好的数据安全性,因为它默认每接收到一个写命令就会追加到文件末尾。即使 Redis 服务器宕机,也只会丢失最后一次写入前的数据。其次,AOF 支持多种同步策略(如 everysec、always 等),可以根据需要调整数据安全性和性能之间的平衡。同时,AOF 文件在 Redis 启动时可以通过重写机制优化,减少文件体积,加快恢复速度。并且,即使文件发生损坏,AOF 还提供了 redis-check-aof 工具来修复损坏的文件。
  • 缺点:因为记录了每一个写操作,所以 AOF 文件通常比 RDB 文件更大,消耗更多的磁盘空间。并且,频繁的磁盘 IO 操作(尤其是同步策略设置为 always 时)可能会对 Redis 的写入性能造成一定影响。而且,当单个文件体积过大时,AOF 会进行重写操作(重写操作会创建一个新的 AOF 文件,新的 AOF 文件仅保留重建当前数据集所需的最小命令集合),AOF 如果没有开启 AOF 重写或者重写频率较低,恢复过程可能较慢,因为它需要重放所有的操作命令。

RDB:

  • 优点:RDB 通过快照的形式保存某一时刻的数据状态,文件体积小,备份和恢复的速度非常快。并且,RDB 是在主线程之外通过 fork 子进程来进行的,不会阻塞服务器处理命令请求,对 Redis 服务的性能影响较小。最后,由于是定期快照,RDB 文件通常比 AOF 文件小得多。
  • 缺点:RDB 方式在两次快照之间,如果 Redis 服务器发生故障,这段时间的数据将会丢失。并且,如果在 RDB 创建快照到恢复期间有写操作,恢复后的数据可能与故障前的数据不完全一致。

Redis 持久化配置

Redis 默认开启 RDB 持久化方式,默认关闭 AOF 持久化方式。

在 Redis 的默认配置文件(redis.conf)中:

  • RDB 配置:默认开启,并设置了以下默认的快照规则:

    save 900 1      # 900 秒(15 分钟)内至少有 1 个 key 被修改则触发保存
    save 300 10     # 300 秒(5 分钟)内至少有 10 个 key 被修改则触发保存
    save 60 10000   # 60 秒内至少有 10000 个 key 被修改则触发保存
    # save ""       # 注释掉所有 save 行可禁用 RDB
    
  • AOF 配置:默认关闭,可以通过设置appendonly yes来开启。开启后,默认的写回策略是 everysec(每秒写回):

    # 启用 AOF(默认 no)
    appendonly yes
    
    # AOF 文件名
    appendfilename "appendonly.aof"
    
    # 同步策略(关键!决定数据安全 vs 性能):
    appendfsync everysec     # ★ 推荐:每秒同步(平衡性能与安全,最多丢 1 秒数据)
    # appendfsync always     # 每次写操作都同步(最安全,但性能差,高延迟)
    # appendfsync no         # 由操作系统决定(最快,但可能丢较多数据)
    
    # AOF 重写(压缩)触发条件:
    auto-aof-rewrite-percentage 100   # 当 AOF 文件比上次重写后增长 100% 时触发
    auto-aof-rewrite-min-size 64mb    # 且文件大小 ≥ 64MB
    
    # 重写期间是否拒绝新写入(建议 no,避免阻塞)
    no-appendfsync-on-rewrite no
    

在实际生产环境中,通常推荐同时开启 RDB 和 AOF 两种持久化方式。这样 RDB 可以作为全量备份,AOF 可以作为实时数据的记录,两者互补,既保证了数据安全性,又提供了较好的恢复性能。优先级:AOF > RDB。Redis 4.0 开始支持 RDB 和 AOF 的混合持久化,通过配置aof-use-rdb-preamble yes开启。

# 必须同时启用 AOF 和 RDB(默认 RDB 已开)
appendonly yes

# 启用混合持久化(Redis 4.0+ 默认 yes)
aof-use-rdb-preamble yes

可通过 redis-cli 在线修改相关配置(临时生效,重启失效):

# 开启 AOF(立即触发重写)
CONFIG SET appendonly yes
# 修改同步策略
CONFIG SET appendfsync everysec

# 手动触发 RDB 快照
BGSAVE
# 手动触发 AOF 重写
BGREWRITEAOF
posted @ 2025-02-09 17:54  Higurashi-kagome  阅读(102)  评论(0)    收藏  举报