Redis——持久化


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 的对比

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

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

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

3. 总结

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值