Redis RDB技术底层原理详解


Posted in Redis onSeptember 04, 2021

每日一句

低头是一种能力,它不是自卑,也不是怯弱,它是清醒中的嬗变。有时,稍微低一下头,或者我们的人生路会更精彩。

前提概要

Redis是一个的键-值(K-V)对的内存数据库服务,通常包含了任意个非空数据库。而每个非空的键值数据库中又可以存放任意个K-V,基本的结构如下图所示:

Redis RDB技术底层原理详解

  • Redis的强劲性能很大程度上是由于其将所有数据都存储在了内存中,为了使Redis在重启之后仍能保证数据不丢失,需要将数据从内存中以某种形式同步到硬盘中,这一过程就是持久化。
  • 我们知道redis中缓存的数据都存放在内存中,一旦服务故障,会导致内存中数据丢失,所以需要一种数据持久化的方案,将redis内存中的数据,写入磁盘,当redis重启后,能从磁盘中恢复数据。

Redis服务器的结构

  • 这里有一个问题,因为Redis是一个内存数据库,如果它直接将数据存储到内存中,但是如果不考虑将存储在内存中的数据持久化到硬盘里面,一旦服务器进程退出,那么数据库中的数据也会消失。
  • 数据库的持久化机制主要有两种,一种是RDB机制,另外一种是AOF机制,AOF机制已经在前面的文章中介绍过了,
  • 如果有兴趣可以去看看,而本文主要讲述RDB机制。

RDB持久化方式

RDB持久化是指在指定的时间间隔内将redis内存中的数据集快照写入磁盘,实现原理是redis服务在指定的时间间隔内先fork一个子进程,由子进程将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储,生成dump.rdb文件存放在磁盘中。

Redis RDB技术底层原理详解

RDB机制

  • Redis提供了RDB持久化能力,这个功能可以将Redis在内存中的数据库状态保持在磁盘里面,避免数据意外丢失。
  • RDB持久化机制可以手动执行,也可以根据服务器配置选定定期执行操作,该功能可以将某一个时间点的数据快照进行保存到一个RDB文件中。

RDB优势

  • 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。
  • 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
  • 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
  • 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。

RDB劣势

如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。

由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。

RDB配置规则

在redis的6379.conf配置文件中:

备份配置参数

save <seconds> <changes>

save <指定时间间隔> <执行指定次数更新操作>,满足条件就将内存中的数据同步到硬盘中。官方出厂配置默认是 900秒内有1个更改,300秒内有10个更改以及60秒内有10000个更改,则将内存中的数据快照写入磁盘。

save 900 1      #在900秒(15分钟)之后,如果至少有一个key发生变化,则dump内存快照
save 300 10     #在300秒(15分钟)之后,如果至少有10个key发生变化,则dump内存快照
save 60 10000   #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照

文件配置参数

默认的rdb文件路径是当前目录,文件名是dump.rdb,可以在配置文件中修改路径和文件名,分别是dir和dbfilename.

# 存放快照的目录
dir ./ # rdb文件存储路径
dbfilename dump.rdb # rdb文件名

压缩配置参数

在进行镜像备份时,是否进行压缩。

rdbcompression yes  #Redis默认是开启压缩的。
# yes:压缩,但是需要一些cpu的消耗。
# no:不压缩,需要更多的磁盘空间。

如果没有触发自动快照,需要对Redis执行手动快照操作,save和bgsave命令来手动快照,两个命令是:

  • SAVE:由主进程进行快照,会阻塞其他请求。
  • BGSAVE:通过fork子进程进行快照,不会阻塞其他请求。

注意:由于Redis使用fork来复制一份当前进程,那么子进程就会占有和主进程一样的内存资源,比如说主进程8G内存,那么在备份的时候,必须保证有16G的内存,要不然会启用虚拟内存,性能非常的差。

快照的过程如下:

  • Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);
  • 父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件;
  • 当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,至此一次快照操作完成。(注意:会存在写一部命令压缩缓存区,记录写入rdb文件时候的操作)

在执行fork的时候操作系统会使用写时复制(copy-on-write)策略,即fork函数发生的一刻父子进程共享同一内存数据,当父进程要更改其中某片数据时(如执行一个写命令),操作系统会将该片数据复制一份以保证子进程的数据不受影响,所以新的RDB文件存储的是执行fork时那一刻的内存快照数据。

通过上述过程可以发现Redis在进行快照的过程中不会修改RDB文件,只有快照结束后才会将旧的文件替换成新的,也就是说任何时候RDB文件都是完整的。这使得可以通过定时备份RDB文件来实现Redis数据库备份。

快照的过程压缩分析:

RDB文件是经过压缩(上文介绍了:可以配置rdbcompression参数以禁用压缩节省CPU占用)的二进制格式,所以占用的空间会小于内存中的数据大小,更加利于传输。

快照的读取加载过程:

  • Redis启动后会读取RDB快照文件,将数据从硬盘载入到内存。根据数据量大小与结构和服务器性能不同,这个时间也不同。通常将一个记录一千万个字符串类型键、大小为1GB的快照文件载入到内存中需要花费20~30秒钟。
  • 通过RDB方式实现持久化,一旦Redis异常退出,就会丢失最后一次快照以后更改的所有数据。这就需要开发者根据具体的应用场合,通过组合设置自动快照条件的方式来将可能发生的数据损失控制在能够接受的范围。如果数据很重要以至于无法承受任何损失,则可以考虑使用AOF方式进行持久化。

RDB 的优缺点

优点:

  1. 适合大规模的数据恢复。
  2. 如果业务对数据完整性和一致性要求不高,RDB是很好的选择。

缺点:

  • 数据的完整性和一致性不高,因为RDB可能在最后一次备份时宕机了。
  • 备份时占用内存,因为Redis 在备份时会独立创建一个子进程,将数据写入到一个临时文件(此时内存中的数据是原来的两倍),最后再将临时文件替换之前的备份文件。
  • 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。(回写和覆盖的时候用的是主进程)。

RDB与AOF二者选择的标准(虽然还没有讲AOF,提前普及)

  • 如果系统是愿意牺牲一些性能,换取更高的缓存一致性(aof)
  • 或者是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。

Redis允许同时开启AOF和RDB,既保证了数据安全又使得进行备份等操作十分容易。此时重新启动Redis后Redis会使用AOF文件来恢复数据,因为AOF方式的持久化可能丢失的数据更少。

总结

  • Redis 默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中。
  • RDB 持久化适合大规模的数据恢复但它的数据一致性和完整性较差。
  • Redis 需要手动开启AOF持久化方式,默认是每秒将写操作日志追加到AOF文件中。

所以Redis的持久化和数据的恢复要选择在夜深人静的时候执行是比较合理的。

到此这篇关于Redis RDB技术底层原理详解的文章就介绍到这了,更多相关Redis RDB底层原理内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Redis 相关文章推荐
在K8s上部署Redis集群的方法步骤
Apr 27 Redis
Redis高级数据类型Hyperloglog、Bitmap的使用
May 24 Redis
redis哨兵常用命令和监控示例详解
May 27 Redis
浅谈Redis主从复制以及主从复制原理
May 29 Redis
深入理解redis中multi与pipeline
Jun 02 Redis
解析Redis Cluster原理
Jun 21 Redis
Redis做数据持久化的解决方案及底层原理
Jul 15 Redis
浅谈redis整数集为什么不能降级
Jul 25 Redis
Redis中有序集合的内部实现方式的详细介绍
Mar 16 Redis
sentinel支持的redis高可用集群配置详解
Apr 01 Redis
Redis官方可视化工具RedisInsight安装使用教程
Apr 19 Redis
详解Redis的三种常用的缓存读写策略步骤
May 06 Redis
使用redis实现延迟通知功能(Redis过期键通知)
Redis集群新增、删除节点以及动态增加内存的方法
Sep 04 #Redis
Redis字典实现、Hash键冲突及渐进式rehash详解
Sep 04 #Redis
基于Redis的List实现特价商品列表功能
Aug 30 #Redis
Redis 常见使用场景
Aug 30 #Redis
Redis入门教程详解
Redis如何实现分布式锁
Aug 23 #Redis
You might like
espresso double下 咖啡粉超细时 饼压力对咖啡的影响
2021/03/03 冲泡冲煮
PHP中HTML标签过滤技巧
2014/01/07 PHP
php简单smarty入门程序实例
2015/06/11 PHP
PHP实现根据数组的值进行分组的方法
2017/04/20 PHP
jquery控制左右箭头滚动图片列表的实例
2013/05/20 Javascript
引用 js在IE与FF之间的区别详细解析
2013/11/20 Javascript
javaScript实现可缩放的显示区效果代码
2015/10/26 Javascript
jQuery的Ajax用户认证和注册技术实例教程(附demo源码)
2015/12/08 Javascript
jQuery ajaxSubmit 实现ajax提交表单局部刷新
2016/07/04 Javascript
jQuery基本选择器之标签名选择器
2016/09/03 Javascript
使用smartupload组件实现jsp+jdbc上传下载文件实例解析
2017/01/05 Javascript
JS出现失效的情况总结
2017/01/20 Javascript
JavaScript截屏功能的实现代码
2017/07/28 Javascript
利用JQUERY实现多个AJAX请求等待的实例
2017/12/14 jQuery
Angular.JS读取数据库数据调用完整实例
2019/07/02 Javascript
基于Element封装一个表格组件tableList的使用方法
2020/06/29 Javascript
vue插件--仿微信小程序showModel实现模态提示窗功能
2020/08/19 Javascript
python实现DNS正向查询、反向查询的例子
2014/04/25 Python
Python中字符串的处理技巧分享
2016/09/17 Python
windows下cx_Freeze生成Python可执行程序的详细步骤
2018/10/09 Python
Python中staticmethod和classmethod的作用与区别
2018/10/11 Python
详解python持久化文件读写
2019/04/06 Python
python移位运算的实现
2019/07/15 Python
使用Python的Turtle绘制哆啦A梦实例
2019/11/21 Python
Python标准库json模块和pickle模块使用详解
2020/03/10 Python
python中selenium库的基本使用详解
2020/07/31 Python
Python项目实战之使用Django框架实现支付宝付款功能
2021/02/23 Python
html5实现移动端适配完美写法
2017/11/16 HTML / CSS
马来西亚最好的婴儿商店:Motherhood
2017/09/14 全球购物
意大利高端时尚买手店:Stefania Mode
2018/03/01 全球购物
新闻专业大学生找工作的自我评价
2013/10/30 职场文书
公司年会抽奖活动主持词
2014/03/31 职场文书
优秀少先队员主要事迹材料
2014/05/28 职场文书
安全生产目标管理责任书
2014/07/25 职场文书
2016习总书记系列重要讲话心得体会
2016/01/15 职场文书
django如何自定义manage.py管理命令
2021/04/27 Python