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》

相关推荐
千月落11 分钟前
Redis数据迁移
数据库·redis·缓存
研究点啥好呢34 分钟前
快手产品经理面试题精选:10道高频考题+答案解析
人工智能·面试·产品经理
FelixBitSoul42 分钟前
缓存淘汰策略全解:从原理到手写实现(Java / Go / Python)
后端·面试
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题】【Java基础篇】第29题:静态代理和动态代理的区别是什么
java·开发语言·后端·面试·代理模式
dovens2 小时前
SpringBoot集成MQTT客户端
java·spring boot·后端
❀͜͡傀儡师2 小时前
Spring Boot 集成 RocksDB 实战:打造高性能 KV 存储加速层
java·spring boot·后端·rocksdb
TeamDev2 小时前
如何在 DotNetBrowser 中使用本地 AI 模型
前端·后端·.net
Rust语言中文社区3 小时前
【Rust日报】2026-05-02 Temper - 用 Rust 编写的 Minecraft 服务器项目发布 0.1.0 版
运维·服务器·开发语言·后端·rust
陈随易3 小时前
2年没用Nodejs了,Bun很香
前端·后端·程序员