Redis:Redis持久化机制

文章目录

  • [Redis 持久化机制](#Redis 持久化机制)
    • RDB (Redis Database)
    • AOF (Append Only File)
      • [AOF 的持久性配置](#AOF 的持久性配置)
      • [AOF 文件被截断或损坏怎么办?](#AOF 文件被截断或损坏怎么办?)
      • [从 RDB 切换到 AOF](#从 RDB 切换到 AOF)
    • [备份 Redis 数据](#备份 Redis 数据)
    • 灾难恢复

Redis 持久化机制

持久化是指将数据写入固态硬盘(SSD)等持久化存储设备的过程。Redis 提供了多种持久化选项,以满足不同场景对性能和数据安全性的需求:

  • RDB (Redis Database):在指定间隔内对数据集执行时间点快照。
  • AOF (Append Only File):记录服务器接收到的每一个写操作。在服务器启动时,通过重新执行这些命令来重建原始数据集。日志记录使用与 Redis 协议本身相同的格式。
  • 无持久化:您可以完全禁用持久化。这在某些纯缓存场景下很常见。
  • RDB + AOF:您可以在同一个实例中同时结合这两种方式。

Persistence_Options
Redis Memory

  1. 按时间间隔快照 2. 记录所有写命令 3. 混合模式 4. 不做任何操作 Redis Data
    RDB File
    AOF File
    Base RDB + Incr AOF
    None / Cache Only

RDB (Redis Database)

RDB 是 Redis 数据集在某个时间点的一个非常紧凑的单一文件表示形式。

  • RDB 的优势

    • 文件紧凑:RDB 文件非常适合备份。例如,您可能希望在最近的 24 小时内每小时归档一次 RDB 文件,并在 30 天内每天保存一个 RDB 快照。这使得在发生灾难时可以轻松恢复不同版本的数据集。
    • 灾难恢复友好:RDB 是一个单一的紧凑文件,可以轻松传输到远程数据中心或 Amazon S3(可能加密)。
    • 性能最大化 :Redis 父进程为了持久化需要做的唯一工作就是 fork 一个子进程来做剩下的事情。父进程永远不会执行磁盘 I/O 或类似操作。
    • 重启速度快:与 AOF 相比,RDB 在大数据集下的重启速度更快。
    • 从节点支持:在从节点上,RDB 支持重启和故障转移后的部分重同步。
  • RDB 的劣势

    • 数据丢失风险:如果需要最大限度地减少 Redis 停止工作(例如断电)时的数据丢失机会,RDB 并不好。您可以配置不同的保存点来生成 RDB(例如至少 5 分钟和 100 次对数据集的写操作),但通常您每五分钟或更久才会创建一次 RDB 快照,因此如果 Redis 因任何原因未正确关闭而停止工作,您应该做好丢失最近几分钟数据的准备。
    • Fork 性能开销 :RDB 需要经常使用 fork() 以便通过子进程将数据持久化到磁盘。如果数据集很大,fork() 可能会很耗时,并可能导致 Redis 停止为客户端服务几毫秒甚至一秒钟(如果数据集非常大且 CPU 性能一般)。AOF 也需要 fork(),但频率较低,并且您可以调整重写日志的频率,而无需在持久性上做出权衡。

磁盘 Redis 子进程 Redis 父进程 磁盘 Redis 子进程 Redis 父进程 父进程继续处理客户端请求 利用 Copy-On-Write 仅复制修改过的内存页 接收 BGSAVE 命令 Fork() 创建子进程 将数据集写入临时 RDB 文件 写入完成 发送完成信号 原子性重命名 temp.rdb ->> dump.rdb

AOF (Append Only File)

AOF 是一种完全持久的策略,它解决了 RDB 可能丢失数据的问题。

  • AOF 的优势

    • 数据持久性更强 :您可以有不同的 fsync 策略:完全不 fsync、每秒 fsync、每次查询都 fsync。在默认的每秒 fsync 策略下,写入性能仍然非常好。fsync 是由后台线程执行的,主线程会努力在没有进行 fsync 时执行写入,因此您最多只会丢失一秒的写入数据。
    • 日志格式安全 :AOF 日志是仅追加日志,因此没有查找问题,也不会出现断电导致的损坏问题。即使日志由于某种原因(磁盘满或其他原因)以半写命令结束,redis-check-aof 工具也能轻松修复它。
    • 自动重写:当 AOF 变得太大时,Redis 能够在后台自动重写 AOF。重写是完全安全的,因为 Redis 继续追加到旧文件,同时产生一个包含创建当前数据集所需的最小操作集的全新文件,一旦第二个文件准备好,Redis 就会切换这两个文件并开始追加到新文件。
    • 易于理解和解析 :AOF 包含所有操作的日志,格式易于理解。您可以轻松导出 AOF 文件。例如,即使您不小心使用 FLUSHALL 命令刷新了所有内容,只要在此期间没有重写日志,您仍然可以通过停止服务器、删除最新命令并再次重启 Redis 来保存数据集。
  • AOF 的劣势

    • 文件体积大:对于相同的数据集,AOF 文件通常比等效的 RDB 文件大。
    • 性能取决于 fsync :根据具体的 fsync 策略,AOF 可能比 RDB 慢。通常,将 fsync 设置为每秒,性能仍然非常高;如果禁用 fsync,即使在重负载下也应该和 RDB 一样快。尽管如此,RDB 仍然能提供关于最大延迟的更多保证。
    • 历史版本 (Redis < 7.0) 的限制
      • 重写期间如果有写入,会占用大量内存(缓冲在内存中,最后写入新 AOF)。
      • 重写期间到达的所有写命令会被写入磁盘两次。
      • Redis 可能在重写结束时冻结写入并将这些写命令 fsync 到新 AOF 文件。

从 Redis 7.0 开始,AOF 引入了一种多部分 AOF 机制。原来的单一 AOF 文件被拆分为:

  1. 基础文件:表示 AOF 重写时存在的初始数据快照(RDB 或 AOF 格式)。
  2. 增量文件:包含自上一个基础 AOF 文件创建以来的增量更改。
  3. 清单文件:用于跟踪这些文件。

这种机制极大地提高了重写效率和安全性。下图展示了 Redis 7.0 中 AOF 重写的过程:
重写完成
重写过程
继续追加写入
生成快照
构建
构建
原子替换
重写前
当前状态
当前状态
旧基础文件
旧 Manifest
旧增量文件
父进程
新增量文件
子进程
新基础文件
临时 Manifest
新 Manifest

AOF 的持久性配置

您可以通过 appendfsync 配置 Redis 将数据 fsync 到磁盘的频率:

  • appendfsync always:每次有新命令追加到 AOF 时都进行 fsync。非常非常慢,但非常安全。
  • appendfsync everysec :每秒 fsync 一次。足够快(从 2.4 版本开始可能和快照一样快),但如果发生灾难,可能会丢失 1 秒的数据。(建议默认策略)
  • appendfsync no:从不 fsync,只是将数据交给操作系统。这是最快且最不安全的方法。通常 Linux 会在此配置下每 30 秒刷新一次数据。

AOF 文件被截断或损坏怎么办?

  • 截断:如果服务器在写入 AOF 文件时崩溃,或者卷已满,AOF 文件的最后一条命令可能不完整。Redis 的最新主要版本仍然能够加载 AOF,只是丢弃文件中最后格式不正确的命令。
  • 损坏 :如果 AOF 文件中间包含无效字节序列,Redis 会报错并中止。最好的方法是运行 redis-check-aof 工具。
    • 首先,不带 --fix 选项运行它以了解问题。
    • 然后,您可以手动修复文件(因为 AOF 使用 Redis 协议格式,很容易修复)。
    • 或者,让工具为您修复文件(这可能会丢弃从无效部分到文件末尾的所有 AOF 部分)。

从 RDB 切换到 AOF

如果您想在当前使用 RDB 快照的服务器上启用 AOF,需要通过 CONFIG 命令在运行中的服务器上转换数据。

  1. 准备
    • 备份您最新的 dump.rdb 文件。
    • 将此备份传输到安全的地方。
  2. 在运行中的数据库上切换
    • 启用 AOF:redis-cli config set appendonly yes
    • (可选)禁用 RDB:redis-cli config set save ""
    • 确保写入被正确追加到仅追加文件中。
    • 重要 :更新您的 redis.conf(可能通过 CONFIG REWRITE),确保配置与上述匹配。如果忘记这一步,重启服务器后配置更改将丢失,服务器将以旧配置重新启动,导致数据丢失。
  3. 下次重启服务器
    • 重启前,等待 AOF 重写完成持久化数据。可以通过 INFO persistence 查看,等待 aof_rewrite_in_progressaof_rewrite_scheduled 为 0,并验证 aof_last_bgrewrite_status 为 ok。

备份 Redis 数据

Redis 对数据备份非常友好,因为您可以在数据库运行时复制 RDB 文件:RDB 一旦生成就不会被修改,并且在生成过程中使用临时名称,仅在新快照完成时使用 rename(2) 原子性地重命名为最终目标。 这意味着在服务器运行时复制 RDB 文件是完全安全的。我们建议:

  1. 在您的服务器中创建一个 cron 作业,在一个目录中创建 RDB 文件的每小时快照,并在不同目录中创建每日快照。
  2. 每次 cron 脚本运行时,确保调用 find 命令以确保删除太旧的快照。
  3. 每天至少一次,确保将 RDB 快照传输到数据中心之外,或至少传输到运行 Redis 实例的物理机之外。

如果您运行仅启用了 AOF 持久化的 Redis 实例,仍然可以执行备份。自 Redis 7.0.0 起,AOF 文件被拆分为多个文件,驻留在由 appenddirname 配置确定的单个目录中。 在正常操作期间,您只需要复制/打包此目录中的文件即可完成备份。但是,如果在重写期间执行此操作,您最终可能会得到无效的备份。为了解决这个问题,您必须在备份期间禁用 AOF 重写

  1. 关闭自动重写:CONFIG SET auto-aof-rewrite-percentage 0
  2. 确保在此期间不要手动启动重写(使用 BGREWRITEAOF)。
  3. 使用 INFO persistence 检查当前没有重写正在进行,验证 aof_rewrite_in_progress 为 0。如果是 1,则需要等待重写完成。
  4. 现在可以安全地复制 appenddirname 目录中的文件。
  5. 完成后重新启用重写:CONFIG SET auto-aof-rewrite-percentage <prev-value>

灾难恢复

Redis 背景下的灾难恢复基本上就是备份的故事,加上将那些备份传输到许多不同的外部数据中心的能力。这样,即使发生影响运行 Redis 并生成其快照的主数据中心的灾难事件,数据也是安全的。
异地多活备份

  1. 生成快照 RDB 2. 定时任务 加密传输
    SCP 安全传输
    Redis 主节点
    本地磁盘
    备份管理
    AWS S3
    远程 VPS
相关推荐
怀旧诚子1 小时前
timeshift之Fedora43设置,已在VM虚拟机验证,待真机验证。
java·服务器·数据库
haixingtianxinghai2 小时前
Redis的定期删除和惰性删除
数据库·redis·缓存
资深web全栈开发2 小时前
PostgreSQL Schema 最佳实践:架构师的命名与组织艺术
数据库·postgresql
麦聪聊数据3 小时前
利用实时数据管道与 SQL2API 重构企业自动化审计架构
数据库·sql·低代码
麦聪聊数据3 小时前
重构开放生态:利用 QuickAPI 跨越遗留系统与敏捷交付的工程实践
数据库·sql·低代码·restful
百结2148 小时前
Mysql数据库操作
数据库·mysql·oracle
keep one's resolveY8 小时前
时区问题解决
数据库
Leinwin8 小时前
OpenClaw 多 Agent 协作框架的并发限制与企业化规避方案痛点直击
java·运维·数据库
qq_417695058 小时前
机器学习与人工智能
jvm·数据库·python