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

Redis 共有三种数据持久化的方式:
- AOF 日志:每执行一条写操作命令,就把该命令以追加的方式写入到一个文件里;
- RDB 快照:将某一时刻的内存数据,以二进制的方式写入磁盘;
- 混合持久化方式:Redis 4.0 新增的方式,集成了 AOF 和 RDB 的优点;
RDB(Redis Database Backup)

Redis 可以通过创建快照来获得存储在内存里面的数据在『某个时间点』上的副本。Redis 创建快照之后,可以对快照进行备份。通过快照的方式,将内存中的数据定期保存到磁盘上,生成一个紧凑的二进制文件(.rdb)。可以将快照复制到其他服务器从而创建具有相同数据的服务器副本,还可以将快照留在原地以便重启服务器的时候使用。
- 优点:文件体积小,恢复速度快,适合大规模数据备份。
- 缺点:如果在两次快照之间发生崩溃,最近的写操作可能会丢失。
Redis 提供了两个命令来生成 RDB 快照文件:
- SAVE:同步保存操作,会阻塞 Redis 主线程;
- BGSAVE:fork 出一个子进程,子进程执行,不会阻塞 Redis 主线程,默认选项。
RDB 基本流程
- 通常是由客户端显式执行上述命令触发,或者由配置的规则触发 RDB 快照。
- 子进程遍历数据库中的键值对,将数据序列化为 RDB 文件格式,并写入临时文件。主进程继续处理请求,期间修改的数据会通过写时复制(Copy-on-Write)技术记录到内存缓冲区。
- 子进程完成写入后,用临时文件原子替换旧的 RDB 文件(如 dump.rdb),确保数据一致性。
- 完成后通过 LASTSAVE 命令可查看最后一次生成 RDB 的时间。
AOF(Append-Only File)

与快照持久化相比,AOF 持久化的实时性更好。默认情况下 Redis 没有开启 AOF(append only file)方式的持久化(Redis 6.0 之后已经默认是开启了)。AOF 通过日志的方式,记录所有对数据库的写操作,保存在一个日志文件(.aof)中。重启时,Redis 会重放这些操作来恢复数据。
- 优点:数据安全性高,几乎不会丢失数据(取决于同步策略)。
- 缺点:文件体积较大,恢复时间较长。
AOF 基本流程
- 所有的写命令会追加到 AOF 缓冲区中。
- 将 AOF 缓冲区的数据写入到 AOF 文件中。
- AOF 缓冲区根据对应的 fsync 策略向硬盘做同步操作。
- 随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的。
- 当 Redis 重启时,可以加载 AOF 文件进行数据恢复。
fsync 同步策略
Redis 支持三种不同的 AOF 持久化方式,它们分别是:always、everysec、no。
- appendfsync always:主线程执行写操作后,后台线程立即会调用 fsync 函数同步 AOF 文件来刷盘,fsync 完成后线程返回。
- appendfsync everysec:主线程执行写操作后立即返回,由后台线程每秒钟调用 fsync 函数(系统调用)同步一次 AOF 文件。
- appendfsync no:主线程执行写操作后立即返回,让操作系统决定何时进行同步。
AOF Rewrite
当 AOF 文件变得太大时,Redis 能够在后台自动重写 AOF 产生一个新的 AOF 文件,这个新的 AOF 文件和原有的 AOF 文件所保存的数据库状态一样,但体积更小。由于 AOF 重写会进行大量的写入操作,为了避免对 Redis 正常处理命令请求造成影响,Redis 将 AOF 重写程序放到子进程里执行。
AOF 文件重写期间,Redis 还会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新的 AOF 文件保存的数据库状态与现有的数据库状态一致。最后,服务器用新的 AOF 文件替换旧的 AOF 文件,以此来完成 AOF 文件重写操作。
混合持久化(Hybrid Persistence)
Redis 4.0 引入的特性,结合 RDB 和 AOF 的优点。在 RDB 文件中嵌入 AOF 的增量数据,既能快速恢复,又能保证较高的数据安全性。
混合持久化的核心思想是:
- 以 RDB 格式保存全量数据:在 AOF 重写时,首先将当前数据库的完整状态以 RDB 的二进制格式写入 AOF 文件的开头。
- 以 AOF 格式记录增量操作:之后的所有写操作以 AOF 文本协议格式追加到 AOF 文件的末尾。
Redis 重启时,优先读取 AOF 文件中的 RDB 格式数据,快速恢复全量基础数据。再回放 AOF 增量操作,执行 AOF 文件末尾的增量命令。这种方式既保留了 RDB 的快速恢复能力,又利用了 AOF 的数据完整性保障。
相关问题
Redis 的持久化技术和 MySQL 的日志机制对比?
MySQL 的 Binlog、Redo log 和 Redis 的 AOF、RDB 都是用于保障数据可靠性和持久性的关键技术,但它们的设计目标、工作原理和使用场景有显著差异。
- Binlog 和 AOF 都关注逻辑变更,适合数据同步和恢复,但 Binlog 更偏向复制和时间点恢复,AOF 是 Redis 持久化的核心,性能开销更大。
- Redo Log 和 RDB 都用于数据恢复,但 Redo Log 是增量日志,保障事务一致性,RDB 是全量快照,适合快速备份但可能丢失数据。
MySQL 的设计更适合事务型、强一致性场景,强调原子性和持久性;Redis 更注重高性能,持久化机制为非强一致性场景优化。这种差异反映了 MySQL 和 Redis 的不同定位:MySQL 是关系型数据库,追求 ACID 特性;Redis 是内存数据库,追求高性能和灵活性。
Redis AOF 和 RDB 机制下恢复数据是如何计算 TTL 的?
在 Redis 使用 AOF 文件恢复数据时,设置了 TTL 的 Key 的剩余时间计算是基于 AOF 文件中记录的命令执行时的『绝对过期时间戳』,并在恢复过程中结合当前时间重新计算得到的。
当在 Redis 中设置一个 Key 的 TTL 时,Redis 不会在 AOF 文件中直接记录相对时间,而是会立即计算出该 Key 的绝对过期时间点的 UNIX 时间戳,精确到毫秒。在 AOF 文件中,记录的是 PEXPIREAT 命令,即使你用的是 EXPIRE。当重放到这条命令时,Redis 会获取当前的系统时间,用记录的绝对过期时间戳减去当前的系统时间戳来计算剩余生存时间。
RDB 持久化在生成快照时,会直接将 Key 的绝对过期时间戳序列化到 .rdb 文件中。恢复加载 RDB 文件时,也是将时间戳直接读入内存,然后在加载完成后依赖当前系统时间计算是否过期。 因此 RDB 恢复 TTL 的原理与 AOF 本质上是相同的,都是依赖记录的绝对时间戳和恢复时的系统时间。
如何选择 RDB 和 AOF?
RDB 文件存储的内容是经过压缩的二进制数据,保存着某个时间点的数据集,文件很小,适合做数据的备份,灾难恢复。使用 RDB 文件恢复数据,直接解析还原数据即可,不需要一条一条地执行命令,速度非常快。而 AOF 则需要依次执行每个写命令,速度非常慢。也就是说,与 AOF 相比,恢复大数据集的时候,RDB 速度更快。
- Redis 保存的数据丢失一些也没什么影响的话,可以选择使用 RDB。
- 不建议单独使用 AOF,因为时不时地创建一个 RDB 快照可以进行数据库备份、更快的重启以及解决 AOF 引擎错误。
- 如果保存的数据要求安全性比较高的话,建议同时开启 RDB 和 AOF 持久化或者开启 RDB 和 AOF 混合持久化。
Redis Big Key 对持久化有什么影响?
Redis 中的 Big Key 指的是占用内存较大、数据量较多的键值对。对持久化机制会产生显著影响,具体表现如下:
- RDB 持久化耗时增加
- 大 Key 的数据量较大,在生成 RDB 快照时需要将完整的数据写入磁盘,导致持久化操作耗时显著增加。这会直接影响 Redis 的性能和响应速度,尤其是在数据集较大的场景下。
- fork 子进程时引发主进程阻塞
- RDB 持久化通过 fork 子进程完成快照生成,而大 Key 会占用较多物理内存,导致主进程在 fork 子进程时需要复制更大的页表,进而增加 fork 的耗时,甚至引发主进程短时阻塞。
- AOF 持久化写入压力增大
- 对于 AOF 持久化,大 Key 的修改或写入操作会产生较大的日志记录(如包含大量元素的集合),增加磁盘 I/O 负载。此外,AOF 重写时同样需要处理大 Key 的完整数据,进一步延长重写时间。
- 内存与网络资源占用升高
- 大 Key 本身占用较多内存,可能导致 Redis 整体内存压力上升,间接影响持久化时的内存管理效率。同时,若大 Key 被频繁访问或持久化,可能因数据传输量过大导致网络带宽饱和。
- 持久化期间性能波动加剧
- 持久化操作本身会消耗 CPU、内存和磁盘 I/O 资源,而大 Key 的存在会放大这些资源的占用,导致 Redis 在持久化期间出现更明显的性能抖动,甚至引发客户端超时阻塞。
大 Key 会显著降低持久化效率,并可能对 Redis 的稳定性和性能造成连锁影响。建议通过拆分数据、优化数据结构等方式减少单个 Key 的体积。