当前位置: 首页 > news >正文

Redis数据持久化机制深度解析

#作者:朱雷

文章目录

  • 一、背景
  • 二、Redis持久化的必要性与影响
    • 1. 持久化的必要性
    • 2. 性能与稳定性问题
  • 三、Redis持久化备份机制详解
    • 1. RDB (Redis Database) 备份
    • 2. AOF (Append Only File) 备份
    • 3、缺点
    • 4、仅附加文件的持久性如何?
    • 5、如果我的 AOF 被截断,我该怎么办?
    • 6、如果我的 AOF 损坏了,我该怎么办?
    • 7、备份策略
  • 六、总结

一、背景

Redis作为一种支持高并发、高性能的内存数据库,其持久化功能是保障数据安全的重要手段。然而,在实际应用中,选择合适的持久化备份机制至关重要。本文将分析Redis持久化备份各种机制组合及其优缺点,并提出持久化备份策略相关建议。

二、Redis持久化的必要性与影响

1. 持久化的必要性

Redis支持多种持久化方式,包括RDB快照和AOF日志。RDB通过定期将内存数据快照写入磁盘,而AOF则记录每次写操作以保证数据一致性。然而,持久化操作会带来额外的性能开销,例如磁盘I/O压力、内存占用以及恢复时间等。

2. 性能与稳定性问题

Redis在高并发场景下频繁进行持久化操作(如RDB快照或AOF重写)可能导致系统阻塞,甚至引发死锁等问题。此外,持久化操作对底层存储介质的要求较高,若存储介质性能不足,可能进一步影响Redis的稳定性。

三、Redis持久化备份机制详解

1. RDB (Redis Database) 备份

1、RDB 持久性会按照指定的时间间隔对数据集执行时间点快照

### 配置 Redis,让其每 N 秒保存一次数据集(如果数据集中至少有 M 个更改),或者您可以手动调用SAVE或BGSAVE命令
save 60 1000
###如果至少有 1000 个键发生变化,此配置将使 Redis 每 60 秒自动将数据集转储到磁盘
工作原理
每当 Redis 需要将数据集转储到磁盘时,就会发生以下情况:
Redis forks 有一个子进程和一个父进程。
子进程开始将数据集写入临时 RDB 文件。
当子进程完成新 RDB 文件的写入后,它将替换旧文件。
这种方法使 Redis 受益于写时复制语义

2、优点

a. RDB 是 Redis 数据的一个非常紧凑的单文件时间点表示。RDB 文件非常适合备份。例如,您可能希望每小时存档最近 24 小时内的 RDB 文件,并每天保存 30 天的 RDB 快照。这样,您就可以在发生灾难时轻松恢复数据集的不同版本。b. RDB 非常适合灾难恢复,它是一个单一的紧凑文件,可以传输到远端数据中心。c. RDB 可最大程度地提高 Redis 的性能,因为 Redis 父进程为了持久化所需要做的唯一工作就是派生一个子进程,然后由子进程来完成其余所有工作。父进程永远不会执行磁盘 I/O 或类似操作。d.与 AOF 相比,RDB 允许使用大数据集更快地重启。e. 在副本上,RDB 支持重启和故障转移后的部分重新同步。

3、缺点
a. 如果您需要尽量减少 Redis 停止工作(例如断电后)时数据丢失的可能性,那么 RDB 并不是一个好选择。您可以配置生成 RDB 的不同保存点(例如,在至少五分钟后对数据集进行 100 次写入后,您可以有多个保存点)。但是,您通常每五分钟或更长时间创建一个 RDB 快照,因此,如果 Redis 因任何原因而未正确关闭而停止工作,您应该准备好丢失最近几分钟的数据。
b. RDB 需要经常使用子进程 fork() 才能将其持久保存在磁盘上。如果数据集很大,fork() 可能会很耗时,如果数据集很大且 CPU 性能不佳,可能会导致 Redis 停止为客户端提供服务几毫秒甚至一秒钟。AOF 也需要 fork(),但频率较低,您可以调整重写日志的频率,而不会影响持久性。

4、backup集群备份
备份主节点RDB文件
./redis-cli --cluster backup 127.0.0.1:6379 ./ 备份到当前数据目录

在这里插入图片描述
在这里插入图片描述
root@redis-app-0:/data# cat /data/nodes.json

[{"name": "105305979bd5c0d93dbf3b6e726940f125c03af9","host": "127.0.0.1","port": 6379,"replicate": null,"slots": [[0,5460]],"slots_count": 5461,"flags": "master","current_epoch": 1},{"name": "843e7e34efbcd5bf6d01b184246644fc88fed9ec","host": "192.168.63.234","port": 6379,"replicate": "a683b94f0d183f23cb50d53aa4fc267cd0b36c39","slots": [],"slots_count": 0,"flags": "slave","current_epoch": 2},{"name": "7efd7f32f97fc0badfb8974fb867f44e0eecedfe","host": "192.168.53.216","port": 6379,"replicate": "f2d4a4bb86736ef4b8aa18a9eaadfe54004d74c3","slots": [],"slots_count": 0,"flags": "slave","current_epoch": 7},{"name": "f7cec783c540b7115dcfb68f9128604bcadded2d","host": "192.168.77.221","port": 6379,"replicate": "105305979bd5c0d93dbf3b6e726940f125c03af9","slots": [],"slots_count": 0,"flags": "slave","current_epoch": 1},{"name": "f2d4a4bb86736ef4b8aa18a9eaadfe54004d74c3","host": "192.168.232.52","port": 6379,"replicate": null,"slots": [[10923,16383]],"slots_count": 5461,"flags": "master","current_epoch": 7},{"name": "a683b94f0d183f23cb50d53aa4fc267cd0b36c39","host": "192.168.104.186","port": 6379,"replicate": null,"slots": [[5461,10922]],"slots_count": 5462,"flags": "master","current_epoch": 2}
]

备份策略
Redis 非常适合数据备份,因为您可以在数据库运行时复制 RDB 文件:RDB 一旦生成就不会被修改,并且在生成时会使用临时名称,并且仅当新的快照完成时才使用 rename(2) 以原子方式重命名为最终目的地。

这意味着在服务器运行时复制 RDB 文件是完全安全的。建议:
a.在您的服务器中创建一个 cron 作业,在一个目录中创建 RDB 文件的每小时快照,并在不同的目录中创建每日快照。

b. 每次运行 cron 脚本时,请务必调用find命令以确保删除过旧的快照:例如,您可以对最近 48 小时进行每小时快照,对一两个月进行每日快照。确保使用日期和时间信息命名快照。

c. 每天至少一次确保将 RDB 快照传输到数据中心之外,或者至少传输到运行 Redis 实例的物理机器之外。

2. AOF (Append Only File) 备份

1、 AOF 持久性记录服务器收到的每个写入操作。然后可以在服务器启动时再次重放这些操作,重建原始数据集。命令使用与 Redis 协议本身相同的格式进行记录。
快照的持久性不是很好。如果运行 Redis 的计算机停止运行、电源线发生故障或者您意外关闭了kill -9实例,写入 Redis 的最新数据将会丢失。虽然这对于某些应用程序来说可能不是什么大问题,但有些用例需要完全的持久​​性,在这些情况下,单独使用 Redis 快照并不是一个最优的选择

### 配置
appendonly yes
### 工作原理
每次 Redis 收到更改数据集的命令(例如SET)时,它都会将其附加到 AOF。重新启动 Redis 时,它将重新播放 AOF 以重建状态
### tips
从 Redis 7.0.0 开始,Redis 使用多部分 AOF 机制。也就是说,原始的单个 AOF 文件被拆分为基本文件(最多一个)和增量文件(可能有多个)。基本文件表示重写 AOF 时存在的数据的初始(RDB 或 AOF 格式)快照。增量文件包含自上次创建基本 AOF 文件以来的增量更改。所有这些文件都放在单独的目录中,并由清单文件跟踪。
### 日志重写
随着写入操作的执行,AOF 会变得越来越大。例如,如果您将计数器递增 100 次,则数据集中最终会有一个包含最终值的键,但 AOF 中有 100 个条目。其中 99 个条目不需要重建当前状态。
重写是完全安全的。Redis 继续向旧文件追加内容的同时,会使用创建当前数据集所需的最少操作集生成一个全新的文件,一旦第二个文件准备就绪,Redis 就会切换这两个文件并开始向新文件追加内容。
因此,Redis 支持能够在后台重建 AOF,而不会中断对客户端的服务。每当您发出 时BGREWRITEAOF,Redis 都会在内存中写入重建当前数据集所需的最短命令序列。如果您在 Redis 2.2 中使用 AOF,则需要BGREWRITEAOF不时运行。因为 Redis ## 2.4 能够自动触发日志重写。从 Redis 7.0.0 开始,当 AOF 重写被调度时,Redis 父进程会开启一个新的增量 AOF 文件继续写入。子进程执行重写逻辑并生成新的基础 AOF。Redis 会使用一个临时的清单文件来追踪新生成的基础文件和增量文件。当它们准备就绪后,Redis 会执行一次原子替换操作来让这个临时的清单文件生效。为了避免 AOF 重写反复失败并重试时产生大量增量文件的问题,Redis 引入了 AOF 重写限制机制,确保失败的 AOF 重试的速度越来越慢。## 2、优点
a. 使用 AOF Redis 的持久性更强:您可以采用不同的 fsync 策略:完全不进行 fsync、每秒进行 fsync、每次查询时进行 fsync。使用每秒进行 fsync 的默认策略,写入性能仍然很好。fsync 使用后台线程执行,主线程会在没有 fsync 进行时尽力执行写入,因此您只会丢失一秒钟的写入。b. AOF 日志是仅附加日志,因此不会出现寻道,也不会在断电时出现损坏问题。即使日志因某种原因(磁盘已满或其他原因)以半写命令结束,redis-check-aof 工具也能够轻松修复它。c. 当 AOF 太大时,Redis 能够在后台自动重写。重写是完全安全的,因为 Redis 在继续向旧文件追加内容的同时,会使用创建当前数据集所需的最少操作集生成一个全新的文件,一旦第二个文件准备就绪,Redis 就会切换这两个文件并开始向新文件追加内容。d. AOF 以易于理解和解析的格式逐一记录所有操作的日志。您甚至可以轻松导出 AOF 文件。例如,即使您不小心使用该FLUSHALL命令刷新了所有内容,只要在此期间没有执行日志重写,您仍然可以通过停止服务器、删除最新命令并重新启动 Redis 来保存数据集。

3、缺点

a. 对于同一数据集,AOF 文件通常比等效的 RDB 文件更大。
b. 根据确切的 fsync 策略,AOF 可能比 RDB 慢。一般来说,将 fsync 设置为每秒一次时,性能仍然非常高,而禁用 fsync 时,即使在高负载下,它也应该与 RDB 一样快。即使在写入负载巨大的情况下,RDB 仍能够提供更多关于最大延迟的保证。

Redis < 7.0

  • 如果在重写期间对数据库进行写入(这些写入会缓冲在内存中并在最后写入新的 AOF),则 AOF 会使用大量内存。
  • 重写期间到达的所有写入命令都会被写入磁盘两次。
  • Redis 可以在重写结束时冻结写入并将这些写入命令 fsync 到新的 AOF 文件。

4、仅附加文件的持久性如何?

您可以配置 Redis 将数据写入磁盘的次数 fsync。有三个选项:

a. appendfsync always:fsync每次将新命令附加到 AOF 时。非常慢,但非常安全。请注意,在执行来自多个客户端或管道的一批命令后,命令才会附加到 AOF,因此这意味着一次写入和一次 fsync(在发送回复之前)。

b. appendfsync everysec:fsync每秒。速度足够快(自 2.4 版以来可能与快照一样快),如果发生灾难,您可能会丢失 1 秒的数据。

c. appendfsync no:永远不要fsync,只需将您的数据交给操作系统即可。这种方法更快,但更不安全。通常,Linux 会使用此配置每 30 秒刷新一次数据,但这取决于内核的精确调整。
建议的(也是默认的)策略是fsync每秒一次。它既快又相对安全。该always策略在实践中非常慢,但它支持组提交,因此如果有多个并行写入,Redis 将尝试执行单个fsync操作。

5、如果我的 AOF 被截断,我该怎么办?

服务器可能在写入 AOF 文件时崩溃,或者存储 AOF 文件的卷在写入时已满。发生这种情况时,AOF 仍包含表示数据集给定时间点版本的一致数据(使用默认 AOF fsync 策略,该版本可能最多为一秒),但 AOF 中的最后一条命令可能会被截断。Redis 的最新主要版本无论如何都能够加载 AOF,只是丢弃文件中最后一条格式不正确的命令。在这种情况下,服务器将发出如下日志:
* Reading RDB preamble from AOF file...
* Reading the remaining AOF tail...
# !!! Warning: short read while loading the AOF file !!!
# !!! Truncating the AOF at offset 439 !!!
# AOF loaded anyway because aof-load-truncated is enabled

6、如果我的 AOF 损坏了,我该怎么办?

如果 AOF 文件不只是被截断,而且中间还包含无效字节序列,那么事情就会变得更加复杂。Redis 会在启动时报错并中止:
* Reading the remaining AOF tail...
# Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename>
最好的办法是运行该redis-check-aof实用程序,最初不带--fix选项,然后了解问题,跳转到文件中的给定偏移量,看看是否可以手动修复文件:AOF 使用与 Redis 协议相同的格式,手动修复非常简单。否则,可以让实用程序为我们修复文件,但在这种情况下,从无效部分到文件末尾的所有 AOF 部分都可能被丢弃,如果损坏恰好发生在文件的起始部分,则会导致大量数据丢失

7、备份策略

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

1、使用关闭自动重写确保在此期间 不要手动启动重写(使用)。
CONFIG SET auto-aof-rewrite-percentage 0
BGREWRITEAOF

2、检查当前没有正在进行的重写, 并且验证是否为 0。如果是 1,那么您需要等待重写完成。
INFO persistence
aof_rewrite_in_progress

3、现在您可以安全地复制目录中的文件appenddirname。

4、完成后重新启用重写:
CONFIG SET auto-aof-rewrite-percentage [1]
注意:如果要尽量减少 AOF 重写被禁用的​​时间,您可以创建指向文件的硬链接appenddirname(在上面的步骤 3 中),然后在创建硬链接后重新启用重写(步骤 4)。现在您可以复制或tar 硬链接并在完成后删除它们。这样做之所以有效,是因为 Redis 保证它只附加到此目录中的文件,或者在必要时完全替换它们,因此内容在任何给定时间点都应该是一致的。
注意:如果您想处理备份期间服务器重启的情况,并确保重启后不会自动启动重写,您可以更改上面的步骤 1,以便通过 保留更新的配置CONFIG REWRITE。只需确保在完成后重新启用自动重写(步骤 4)并将其与另一个 一起保留即可CONFIG REWRITE。
在 7.0.0 版本之前,备份 AOF 文件只需复制 aof 文件即可(就像备份 RDB 快照一样)。文件可能缺少最后部分,但 Redis 仍将能够加载它

六、总结

Redis 持久化机制通过 ‌RDB‌ 和 ‌AOF‌ 两种方式保障数据可靠性。RDB 以快照形式定时保存内存数据,适合全量备份,恢复速度快但可能丢失部分数据;AOF 记录所有写操作命令,支持实时同步,数据安全性高但文件体积较大。
实际应用中可结合两者:RDB 用于定期全量备份,AOF 记录增量操作,通过配置 appendfsync everysec 平衡性能与数据一致性。混合模式进一步优化了恢复效率,兼顾数据完整性和备份灵活性。

http://www.lqws.cn/news/165763.html

相关文章:

  • 从零开始的嵌入式学习day33
  • 【Fifty Project - D33】
  • select、poll、epoll 与 Reactor 模式
  • UI学习—cell的复用和自定义cell
  • linux 串口调试命令 stty
  • SELinux是什么以及如何编写SELinux策略
  • Git操作记录
  • 知识蒸馏:从模型输出到深层理解
  • JAVA开发工具——IntelliJ IDEA
  • 在不同型号的手机或平板上后台运行Aidlux
  • 上门预约行业技术方案全解析:小程序、App还是H5?如何选择?
  • Nature Methods | OmiCLIP:整合组织病理学与空间转录组学的AI模型
  • 【JavaWeb】Linux项目部署
  • 复变函数中的对数函数及其MATLAB演示
  • 如何利用Haption力反馈遥操作机器人解决远程操作难题
  • 2021 RoboCom 世界机器人开发者大赛-高职组(初赛)解题报告 | 珂学家
  • Linux Core 文件查看和调试
  • 第七十四篇 高并发场景下的Java并发容器:用生活案例讲透技术原理
  • 用 NGINX 构建高效 SMTP 代理`ngx_mail_smtp_module`
  • 深度学习N2周:构建词典
  • 板凳-------Mysql cookbook学习 (十)
  • ReLU 激活函数:重大缺陷一去不复返!
  • reverse笔记
  • 目标检测实战:让AI“看见“并定位物体(superior哥AI系列第11期)
  • Web后端基础(Maven基础)
  • 8天Python从入门到精通【itheima】-69~70(字符串的常见定义和操作+案例练习)
  • 从Copilot到Agent,AI Coding是如何进化的?
  • 2025爱分析·银行数字化应用实践报告|爱分析报告
  • [闭源saas选项]Pinecone:为向量数据库而生的实时语义搜索引擎
  • 关于智能体API参考接口