文章目录
- [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
- 按时间间隔快照 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 文件被拆分为:
- 基础文件:表示 AOF 重写时存在的初始数据快照(RDB 或 AOF 格式)。
- 增量文件:包含自上一个基础 AOF 文件创建以来的增量更改。
- 清单文件:用于跟踪这些文件。
这种机制极大地提高了重写效率和安全性。下图展示了 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 命令在运行中的服务器上转换数据。
- 准备 :
- 备份您最新的
dump.rdb文件。 - 将此备份传输到安全的地方。
- 备份您最新的
- 在运行中的数据库上切换 :
- 启用 AOF:
redis-cli config set appendonly yes - (可选)禁用 RDB:
redis-cli config set save "" - 确保写入被正确追加到仅追加文件中。
- 重要 :更新您的
redis.conf(可能通过CONFIG REWRITE),确保配置与上述匹配。如果忘记这一步,重启服务器后配置更改将丢失,服务器将以旧配置重新启动,导致数据丢失。
- 启用 AOF:
- 下次重启服务器 :
- 重启前,等待 AOF 重写完成持久化数据。可以通过
INFO persistence查看,等待aof_rewrite_in_progress和aof_rewrite_scheduled为 0,并验证aof_last_bgrewrite_status为 ok。
- 重启前,等待 AOF 重写完成持久化数据。可以通过
备份 Redis 数据
Redis 对数据备份非常友好,因为您可以在数据库运行时复制 RDB 文件:RDB 一旦生成就不会被修改,并且在生成过程中使用临时名称,仅在新快照完成时使用 rename(2) 原子性地重命名为最终目标。 这意味着在服务器运行时复制 RDB 文件是完全安全的。我们建议:
- 在您的服务器中创建一个 cron 作业,在一个目录中创建 RDB 文件的每小时快照,并在不同目录中创建每日快照。
- 每次 cron 脚本运行时,确保调用
find命令以确保删除太旧的快照。 - 每天至少一次,确保将 RDB 快照传输到数据中心之外,或至少传输到运行 Redis 实例的物理机之外。
如果您运行仅启用了 AOF 持久化的 Redis 实例,仍然可以执行备份。自 Redis 7.0.0 起,AOF 文件被拆分为多个文件,驻留在由 appenddirname 配置确定的单个目录中。 在正常操作期间,您只需要复制/打包此目录中的文件即可完成备份。但是,如果在重写期间执行此操作,您最终可能会得到无效的备份。为了解决这个问题,您必须在备份期间禁用 AOF 重写:
- 关闭自动重写:
CONFIG SET auto-aof-rewrite-percentage 0 - 确保在此期间不要手动启动重写(使用
BGREWRITEAOF)。 - 使用
INFO persistence检查当前没有重写正在进行,验证aof_rewrite_in_progress为 0。如果是 1,则需要等待重写完成。 - 现在可以安全地复制
appenddirname目录中的文件。 - 完成后重新启用重写:
CONFIG SET auto-aof-rewrite-percentage <prev-value>
灾难恢复
Redis 背景下的灾难恢复基本上就是备份的故事,加上将那些备份传输到许多不同的外部数据中心的能力。这样,即使发生影响运行 Redis 并生成其快照的主数据中心的灾难事件,数据也是安全的。
异地多活备份
- 生成快照 RDB 2. 定时任务 加密传输
SCP 安全传输
Redis 主节点
本地磁盘
备份管理
AWS S3
远程 VPS