Redis——持久化

发布于:2025-02-11 ⋅ 阅读:(55) ⋅ 点赞:(0)


1. 引入

Redis 的数据保存在 缓存 中,一旦服务器断电/宕机,数据就无法恢复。为了避免这个问题,需要把 Redis 的数据 持久化 到磁盘等存储介质上,从而在服务器重启后,能够从持久化的文件中恢复数据。

此外,Redis 的持久化文件可用于做 迁移恢复。如果想把一台 Redis 中的数据迁移到另一台 Redis 中,则可以使用持久化文件;在执行错误操作后,可以通过持久化文件恢复数据。

2. 持久化方案

2.1 方案一:RDB

2.1.1 介绍

RDB (Redis Database Backup,Redis 数据备份):也叫做 Redis 数据快照,实际上就是把 内存中的数据 记录到磁盘中。当 Redis 实例故障重启后,从磁盘读取快照文件,恢复数据。

2.1.2 触发 RDB 的指令

在登录 Redis 客户端后,可以使用如下的指令来使用 RDB:

save # 由 Redis 主进程来执行 RDB,会阻塞其它的所有命令
bgsave # Redis 开启子进程来执行 RDB,不会阻塞其它命令

2.1.3 触发 bgsave 的机制

如果想要定时/定量将 Redis 中的数据持久化到磁盘中,每次都手敲一遍 save/bgsave 指令还是比较麻烦的。Redis 中提供了触发 bgsave 的机制,可以在 redis.conf 配置文件中进行配置:

save 60 10      # 60s 内,如果至少有 10 个键被修改,则执行一次 RDB 操作
save 300 100    # 300s 内,如果至少有 100 个键被修改,则执行一次 RDB 操作

2.1.4 bgsave 的执行原理

要想理解 bgsave,必须要先了解 Linux 操作系统的以下知识:

(1) 页表

在 Linux 系统中,所有进程都无法操作物理内存,操作系统会给每个进程分配一片 虚拟内存,每个进程只能操作虚拟内存,操作系统会维护一个 虚拟内存 和 物理内存 之间的映射关系表,这个表叫做 页表,它主要记录 虚拟地址 与 物理地址 的映射关系。Redis 进程基于页表中的虚拟地址,关联到物理地址,从而实现对物理内存的读写操作。

(2) fork

fork 是 Unix/Linux 操作系统中的一个系统调用,它的主要作用是从一个现有进程(父进程)创建一个新进程(子进程)。当 fork 被调用时,操作系统会复制父进程的几乎所有资源,包括内存空间(使用 Copy-on-Write 技术优化)。

(3) COW

COW (Copy-on-Write,写时复制技术):在 fork 后,子进程拷贝父进程的页表,而不是拷贝父进程操作的物理内存,实现内存空间的共享,避免消耗大量的时间和资源。只有当父进程或者子进程尝试修改某个内存页时,操作系统才会真正复制该内存页。这样可以大大减少 fork 操作后的内存开销。

(4) bgsave 的执行原理

当触发 bgsave 后,Redis 使用 fork 系统调用创建子进程,这个子进程与父进程 (即 Redis 进程) 通过 页表 共享内存中的数据。子进程用于复制,不可能修改数据,而父进程可能会修改数据,这时操作系统会将待修改的数据复制一份,父进程使用复制出来的新数据,子进程使用原本的旧数据,从而实现 Redis 子进程的数据备份。

2.2 方案二:AOF

2.2.1 介绍

AOF (Append Only File,追加文件):Redis 会将每个 写命令 都记录到磁盘中,和 MySQL 的 binlog 日志文件类似。

2.2.2 AOF 的配置

AOF 功能可以在 redis.conf 配置文件中配置:

appendonly yes              # 是否打开 AOF 功能,默认是 no
appendfilename "xxx.aof"    # AOF 文件的名称

appendfsync always      # 同步刷盘:每执行完一次写命令,立即刷盘
appendfsync everysec    # 每秒刷盘:写命令执行完先放入 AOF 缓冲区,每间隔 1s 将缓存区数据刷盘,是默认方案
appendfsync no          # 操作系统控制刷盘:写命令执行完先放入 AOF 缓冲区,由操作系统决定何时将缓冲区数据刷盘

2.2.3 AOF 刷盘策略的比较

配置 刷盘时机 性能 可靠性
always 同步刷盘 最低 几乎不丢数据
everysec 每秒刷盘 适中 最多丢 1s 的数据
no 操作系统控制刷盘 最高 可能丢失大量数据

2.2.4 AOF 的缺点及补救措施

(1) 缺点的介绍

由于 AOF 会记录每个写命令,而不是记录具体的数据,所以 AOF 这种持久化方式占用的空间比较大。

(2) 缺点的举例

例如,对于 RDB,如果有这几个写命令 set value 1; set data 2; set value 3,那么最终只会记录有两个 string 数据类型的数据 value:1, data:2;而对于 AOF,它需要记录这三条写命令,明显就比 RDB 占用的空间大。

(3) 补救措施的介绍

在 Redis 中,对此也作出了补救的措施——执行 bgrewriteof 命令,执行这条命令后,就可以让 AOF 文件执行 重写 功能,用最少的命令达到相同的效果。

(4) 补救措施的举例

例如上面的 set value 1; set data 2; set value 3 通过 bgrewriteof 命令重写之后,就变成 mset data 2 value 3 了,避免了一些无效的写入,并减少了指令的数量。

(5) 补救措施的自动触发

Redis 也会在 AOF 文件达到某个阈值时自动重写它,可以在 redis.conf 中配置:

auto-aof-rewrite-percentage 75  # AOF 文件相比上次文件增长超过 %多少 才会触发重写
auto-aof-rewrite-min-size 16mb  # AOF 文件的大小最小为 多少 才会触发重写

2.3 RDB 和 AOF 的对比

持久化方式 RDB AOF
持久化的数据 内存中的所有数据 每条写命令
数据完整性 不完整,两次备份之间的数据会丢失 相对完整,具体与刷盘策略有关
文件大小 只存储数据,还进行了压缩,文件体积小 存储所有写命令,文件体积大
宕机恢复速度 快,因为文件小 慢,因为文件大
数据恢复优先级 低,因为完整性不如 AOF 高,因为数据完整性更高
系统资源占用 高,占用大量 CPU 和内存资源 低,主要占用磁盘 IO 资源,但 AOF 重写时会占用大量 CPU 和内存资源
使用场景 可以容忍数分钟的数据丢失,追求更快的启动速度 对数据安全性要求较高

在开发中,RDB 和 AOF 可以一起使用,优势如下:

  • 数据安全性增强:RDB 提供了数据的定期快照备份,而 AOF 提供了更细粒度的写操作记录。这样,即使一个文件因为某些原因损坏,还可以利用另一个文件恢复数据。
  • 性能与恢复速度的平衡:RDB 的 快速恢复特性 在需要快速重启服务并且可以接受一定程度的数据丢失时非常有用。而 AOF 在保证 数据完整性 方面发挥作用,在日常运行中记录所有的写操作,以应对意外情况。

3. 总结

Redis 保存在内存中的数据可以持久化到磁盘中,从而达到重启后恢复数据或迁移数据的效果。

具体实现方式主要有两种:

  • RDB:Redis 的数据快照,隔一段时间触发就会保存一次快照。宕机恢复的速度比较快,但可能会丢失一部分数据。
  • AOF:Redis 写命令的日志文件,有不同的刷盘策略,默认每秒刷盘一次,不仅性能不低,也不会丢失很多数据。数据相较 RDB 更完整。

在生产中,可以同时发挥这两种方式的优点,不仅宕机恢复的速度快,而且也能保证数据的完整性。


网站公告

今日签到

点亮在社区的每一天
去签到