Redis持久化技术之RDB快照 学习笔记

前言

所谓快照,就是记录某一瞬间的内存数据,因此,不同于AOF日志记录的是操作命令,RDB文件的内容是二进制数据。因此在Redis恢复数据时,采用RDB的效率会更高,直接将RDB文件读入内存即可,不需要像AOF那样还需要额外执行命令来恢复数据

RDB实现原理

Redis提供了两个命令来生成RDB文件,区别在于是否在主进程里执行:

  • save:在主进程里生成RDB文件,由于和执行操作命令在同个进程,所以如果写入时间过长,会阻塞主进程
  • bgsave:创建一个子进程来生成RDB文件,避免阻塞主进程

Redis并没有提供专门用于加载RDB文件的命令,是在服务器启动时自动执行RDB文件的加载

不过,如果采用的是bgsave命令,可以通过配置来实现命令自动执行,默认配置如下:

save 900 1
save 300 10
save 60 10000

解释:

  • 900秒之内,对数据库进行了至少1次修改,就会执行bgsave
  • 300秒之内,对数据库进行了至少10次修改,就会执行bgsave
  • 60秒之内,对数据库进行了至少10000次修改,就会执行bgsave

性能分析

注意:Redis的快照是全量快照,即每次执行快照时,都是把内存中的所有数据记录到磁盘中。

可以认为执行快照是一个比较重的操作,如果太频繁可能对Redis产生性能影响;但是如果频率太低,发生故障时,丢失的数据会更多。

通常设置至少5分钟才保存一次RDB快照,这时如果Redis发生宕机,最多丢失5分钟数据

这就是RDB快照的缺点,在发生服务器故障时,丢失的数据会比AOF持久化方式更多,因为RDB快照是采用全量快照的方式,因此执行频率不能太频繁,否则影响Redis性能,而AOF日志可以秒级记录操作命令,相对丢失的数据更少。

bgsave写时复制

执行bgsave过程中,Redis依然可继续处理命令,主进程会通过fork()创建子进程,此时父子进程共享同一片内存数据,页表执行同个物理内存空间。

发生修改内存数据时,物理内存会被复制一份(仅复制被修改的部分,未修改的部分仍共享) 例如,如果主线程(父进程)要修改共享数据里的某一块数据 (比如键值对 A)时,发生写时复制,于是这块数据的物理内存就会被复制一份(键值对 A' ,然后主线程在这个数据副本(键值对 A')进行修改操作 ,与此同时,bgsave 子进程可以继续把原来的数据(键值对 A)写入到 RDB 文件

写时复制的目的是减少创建子进程的性能损耗,从而加快创建子进程速度,毕竟创建子进程是会阻塞主进程的。

数据不一致

bgsave过程中,如果主进程修改了共享数据,发生写时复制后,RDB快照保存的是原来的内存数据,而主进程刚修改的数据,只能交由下一次的bgsave命令。

如果恰好系统在RDB快照文件创建完毕后宕机,那么Redis将丢失主进程此前在该写快照期间修改的数据

内存占用激增

在Redis执行RDB持久化期间,刚fork时,主进程和子进程共享同一物理内存数据,但途中主进程处理了写操作,修改了共享内存,于是当前被修改数据的物理内存就被复制一份。

极端情况下,如果所有的共享内存都被修改了,此时的内存占用将是原来的2倍。

因此,针对写操作多的场景,要留意下RDB快照记录过程的内存变化,防止OOM。

参考

《小林coding》

相关推荐
m0_748240913 小时前
Auto-go 环境配置
开发语言·后端·golang
黑夜无路人3 小时前
redis底层数据结构——整数集合
数据结构·redis
星星点点洲5 小时前
【SpringBoot实现全局API限频】 最佳实践
java·spring boot·后端
华梦岚5 小时前
F#语言的学习路线
开发语言·后端·golang
lllsure5 小时前
【快速入门】SpringMVC
java·后端·spring·mvc
一包烟电脑面前做一天6 小时前
C#、.Net 中级高级架构管理面试题杂烩
面试·架构·c#·.net·面试题
梅清瑶6 小时前
Powershell语言的数据库编程
开发语言·后端·golang
阿芯爱编程6 小时前
java面试题
java·后端
Asthenia04127 小时前
BigDecimal:从实现机制分析入参为何得是字符串&&CompareTo与Equals
后端
m0_748240257 小时前
【Spring Boot】统一数据返回
java·spring boot·后端