文章目录
- 1. 引入
- 2. 持久化方案
- 2.1 方案一:RDB
- 2.1.1 介绍
- 2.1.2 触发 RDB 的指令
- 2.1.3 触发 bgsave 的机制
- 2.1.4 bgsave 的执行原理
- (1) 页表
- (2) fork
- (3) COW
- (4) bgsave 的执行原理
- 2.2 方案二:AOF
- 2.2.1 介绍
- 2.2.2 AOF 的配置
- 2.2.3 AOF 刷盘策略的比较
- 2.2.4 AOF 的缺点及补救措施
- (1) 缺点的介绍
- (2) 缺点的举例
- (3) 补救措施的介绍
- (4) 补救措施的举例
- (5) 补救措施的自动触发
- 2.3 RDB 和 AOF 的对比
- 3. 总结
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 更完整。
在生产中,可以同时发挥这两种方式的优点,不仅宕机恢复的速度快,而且也能保证数据的完整性。