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
相关推荐
阿里-于怀2 小时前
AgentScope AutoContextMemory:告别 Agent 上下文焦虑
android·java·数据库·agentscope
数据库那些事儿2 小时前
从极速复制“死了么”APP,看AI编程时代的技术选型
数据库
岁岁种桃花儿2 小时前
MySQL知识汇总:讲一讲MySQL中Select语句的执行顺序
数据库·mysql·database
言之。2 小时前
Django原子请求
数据库·django·sqlite
Codeking__3 小时前
Redis初识——Redis的基本特性
数据库·redis·缓存
零度@3 小时前
2026 轻量级消息队列 Redis Stream
前端·redis·bootstrap
霖霖总总3 小时前
[小技巧29]Batched Key Access:MySQL JOIN 性能优化的关键技术
数据库·mysql·性能优化
Gobysec3 小时前
Goby 漏洞安全通告|MindsDB /api/sql/query 未授权访问漏洞(CVE-2025-68472)
数据库·sql·安全
m0_748245923 小时前
SQLite 数据类型概述
java·数据库·sqlite