首页 > 数据库 >Redis持久化----RDB

Redis持久化----RDB

时间:2022-10-27 21:11:44浏览次数:43  
标签:快照 Redis ---- 修改 内存 RDB 数据

Redis持久化----RDB

原理

当采用RDB这种方式来持久化Redis中的数据时,是向RDB文件中写入redis的快照;

什么是内存快照:

​ 所谓内存快照,就是指内存中的数据在某⼀个时刻的状态记录。这就类似于照⽚,当你给朋友拍照时,⼀张照⽚就能把朋友⼀瞬间的形象完全 记下来。

​ 对Redis来说,它实现类似照⽚记录效果的⽅式,就是把某⼀时刻的状态以⽂件的形式写到磁盘上,也就是快照。这样⼀来,即使宕机,快照⽂件也不会丢失,数据的可靠性也就得到了保证。这个快照⽂件就称为 RDB⽂件,其中,RDB就是Redis DataBase的缩写.

RDB的优点

在做内存恢复时数据比AOF快很多

原因:RDB记录的是某⼀时刻的数据,并不是操作,所以,在做数据恢复时,我们可以直接把RDB⽂ 件读⼊内存,很快地完成恢复。

RDB文件是给哪些数据做快照?

​ Redis的数据都在内存中,为了提供所有数据的可靠性保证,它执⾏的是全量快照,也就是说,把内存中的所有数据都记录到磁盘中;

redis是如何生成RDB文件的

Redis提供了两个命令来⽣成RDB⽂件,分别是save和bgsave。

  • save:在主线程中执⾏,会导致阻塞;
  • bgsave:创建⼀个⼦进程,专⻔⽤于写⼊RDB⽂件,避免了主线程的阻塞,这也是Redis RDB⽂件⽣成的默认配置

快照时数据能修改吗?

​ 在给别⼈拍照时,⼀旦对⽅动了,那么这张照⽚就拍糊了,我们就需要重拍,所以我们当然希望对⽅保持不 动。对于内存快照⽽⾔,我们也不希望数据“动”。

举个例⼦。我们在时刻t给内存做快照,假设内存数据量是4GB,磁盘的写⼊带宽是0.2GB/s,简单来说,⾄少需要20s(4/0.2 = 20)才能做完。如果在时刻t+5s时,⼀个还没有被写⼊磁盘的内存数据A,被修改成了 A’,那么就会破坏快照的完整性,因为A’不是时刻t时的状态。因此,和拍照类似,我们在做快照时也不 希望数据“动”,也就是不能被修改。;

​ 但是,如果快照执⾏期间数据不能被修改,是会有潜在问题的。对于刚刚的例⼦来说,在做快照的20s时间 ⾥,如果这4GB的数据都不能被修改,Redis就不能处·理对这些数据的写操作,那⽆疑就会给业务服务造成巨⼤的影响

​ 你可能会想到,可以⽤bgsave避免阻塞啊。这⾥我就要说到⼀个常⻅的误区了,避免阻塞和正常处理写操作并不是⼀回事。此时,主线程的确没有阻塞,可以正常接收请求,但是,为了保证快照完整性,它只能处理读操作,因为不能修改正在执⾏快照的数据。

​ 为了快照⽽暂停写操作,肯定是不能接受的。所以这个时候,Redis就会借助操作系统提供的写时复制技术 (Copy-On-Write, COW),在执⾏快照的同时,正常处理写操作。

Redis中的COW

​ 简单来说,bgsave⼦进程是由主线程fork⽣成的,可以共享主线程的所有内存数据。bgsave⼦进程运⾏ 后,开始读取主线程的内存数据,并把它们写⼊RDB⽂件。

​ 此时,如果主线程对这些数据也都是读操作(例如图中的键值对A),那么,主线程和bgsave⼦进程相互不影响。但是,如果主线程要修改⼀块数据(例如图中的键值对C),那么,这块数据就会被复制⼀份,⽣成该数据的副本。然后,bgsave⼦进程会把这个副本数据写⼊RDB⽂件,⽽在这个过程中,主线程仍然可以 直接修改原来的数据。

​ 这既保证了快照的完整性,也允许主线程同时对数据进⾏修改,避免了对正常业务的影响。

​ 到这⾥,我们就解决了对“哪些数据做快照”以及“做快照时数据能否修改”这两⼤问题:Redis会使⽤ bgsave对当前内存中的所有数据做快照,这个操作是⼦进程在后台完成的,这就允许主线程同时可以修改数据。

多久做⼀次快照?

​ 快照的间隔时间变得很短,即使某⼀时刻发 ⽣宕机了,因为上⼀时刻快照刚执⾏,丢失的数据也不会太多。但是,这其中的快照间隔时间就很关键了。

如下图所⽰,我们先在T0时刻做了⼀次快照,然后⼜在T0+t时刻做了⼀次快照,在这期间,数据块5和9被修改了。如果在t这段时间内,机器宕机了,那么,只能按照T0时刻的快照进⾏恢复。此时,数据块5和9的修改值因为没有快照记录,就⽆法恢复了。

​ 所以,要想尽可能恢复数据,t值就要尽可能⼩,t越⼩,就越像“连拍”。那么,t值可以⼩到什么程度 呢,⽐如说是不是可以每秒做⼀次快照?毕竟,每次快照都是由bgsave⼦进程在后台执⾏,也不会阻塞主线程。

这种想法其实是错误的。虽然bgsave执⾏时不阻塞主线程,但是,如果频繁地执⾏全量快照,也会带来两 ⽅⾯的开销。

  • 一⽅⾯,频繁将全量数据写⼊磁盘,会给磁盘带来很⼤压⼒,多个快照竞争有限的磁盘带宽,前⼀个快照还 没有做完,后⼀个⼜开始做了,容易造成恶性循环。
  • 另⼀⽅⾯,bgsave⼦进程需要通过fork操作从主线程创建出来。虽然,⼦进程在创建后不会再阻塞主线程, 但是,fork这个创建过程本⾝会阻塞主线程,⽽且主线程的内存越⼤,阻塞时间越⻓。如果频繁fork出 bgsave⼦进程,这就会频繁阻塞主线程了。那么,有什么其他好⽅法吗?

​ 此时,我们可以做增量快照,所谓增量快照,就是指,做了⼀次全量快照后,后续的快照只对修改的数据进 ⾏快照记录,这样可以避免每次全量快照的开销。

在第⼀次做完全量快照后,T1和T2时刻如果再做快照,我们只需要将被修改的数据写⼊快照⽂件就⾏。但 是,这么做的前提是,我们需要记住哪些数据被修改了。你可不要⼩瞧这个“记住”功能,它需要我们使⽤ 额外的元数据信息去记录哪些数据被修改了,这会带来额外的空间开销问题。如下图所⽰:

如果我们对每⼀个键值对的修改,都做个记录,那么,如果有1万个被修改的键值对,我们就需要有1万条额 外的记录。⽽且,有的时候,键值对⾮常⼩,⽐如只有32字节,⽽记录它被修改的元数据信息,可能就需要 8字节,这样的画,为了“记住”修改,引⼊的额外空间开销⽐较⼤。这对于内存资源宝贵的Redis来说,有 些得不偿失。

到这⾥,你可以发现,虽然跟AOF相⽐,快照的恢复速度快,但是,快照的频率不好把握,如果频率太低, 两次快照间⼀旦宕机,就可能有⽐较多的数据丢失。如果频率太⾼,⼜会产⽣额外开销,那么,还有什么⽅ 法既能利⽤RDB的快速恢复,⼜能以较⼩的开销做到尽量少丢数据呢?

理论上的最优解--混合模式

Redis 4.0中提出了⼀个混合使⽤AOF⽇志和内存快照的⽅法。简单来说,内存快照以⼀定的频率执⾏,在两 次快照之间,使⽤AOF⽇志记录这期间的所有命令操作。

这样⼀来,快照不⽤很频繁地执⾏,这就避免了频繁fork对主线程的影响。⽽且,AOF⽇志也只⽤记录两次 快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现⽂件过⼤的情况了,也可以避免重写开销。

如下图所⽰,T1和T2时刻的修改,⽤AOF⽇志记录,等到第⼆次做全量快照时,就可以清空AOF⽇志,因为 此时的修改都已经记录到快照中了,恢复时就不再⽤⽇志了。

这个⽅法既能享受到RDB⽂件快速恢复的好处,⼜能享受到AOF只记录操作命令的简单优势,颇有点“⻥和 熊掌可以兼得”的感觉。

总结

  • 数据不能丢失时,内存快照和AOF的混合使⽤是⼀个很好的选择;
  • 如果允许分钟级别的数据丢失,可以只使⽤RDB;
  • 如果只⽤AOF,优先使⽤everysec的配置选项,因为它在可靠性和性能之间取了⼀个平衡

标签:快照,Redis,----,修改,内存,RDB,数据
From: https://www.cnblogs.com/xuzhidong/p/16833732.html

相关文章

  • manacher
    manacher\(manacher\),一个可以做到\(O(n)\)求解一个字符串中的所有回文子串。我们有一种\(O(n^2)\)的算法来求回文子串,枚举回文中心一点一点比较。基于\(O(n^2)\)......
  • 磁盘存储器
    https://www.icourse163.org/course/NJU-1001964032?tid=1206628248第三周磁盘存储器引言第1讲磁盘存储器的结构第2讲 磁盘驱动器以及操作过程第3讲 磁盘存储器的......
  • 1-turtle坐标
    1-坐标见如下:2-获取坐标importturtlep=turtle.Pen()#画布中心,起始位置pos=p.position()#(0.00,0.00)2-设置(移动)坐标......
  • 跟着应老师学制版(第2季)视频教程
    课程目标:让初学入门者,熟练、系统、全面掌握PSAICDR以及印前技术,搭建起完整的知识体系,本目录发布80节课程。适合人群:印前设计初学者本课程,发布为80节,实际550节,付款后,加......
  • xcode14 初探
    创建新项目......
  • MySQL向表中添加列
    我们使用altertableaddcolumn语句向现有表中添加新列。简介altertabletable_nameadd[column]column_namecolumn_definition[first|afterexisting_column];......
  • SparkSQL(二)
    【理解】SparkSQL执行流程接收到查询,既可以是SQL语句,也可以是DSL语法,以一个SQL语句为例:1、Parser,第三方类库Antlr实现。将sql字符串切分成Token,根据语义规则......
  • vagrant + vmware 创建centos7虚拟机
    安装vagrant安装vmware-utility配置环境变量下载vmware-desktop插件vagrantplugininstallvagrant-vmware-desktop下载centos7-boxhttps://mirrors.us......
  • 第六章 函数
    6.1函数基础调用函数:函数的调用将完成两项工作,一是实参初始化函数对应的形参;二是控制权从从主调函数转移到被调函数,主调函数的执行被中断,被调函数开始执行。当函数遇到ret......
  • 浅谈差分约束
    差分约束也是个咕了很久的简单玩意。俺咕诶总述主要思想是转化为图论问题。对于一大堆\(x-y\leqw\)求可行解,移个项发现变成了\(x\leqy+w\)注意到这玩意......