内存快照:宕机后,Redis如何实现快速恢复,90%的人看完都说好

简单来说,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只记录操作命令的简单优势,颇有点“鱼和熊掌可以兼得”的感觉,建议你在实践中用起来。

小结

这节课,我们学习了Redis用于避免数据丢失的内存快照方法。这个方法的优势在于,可以快速恢复数据库,也就是只需要把RDB文件直接读入内存,这就避免了AOF需要顺序、逐一重新执行操作命令带来的低效性能问题。

不过,内存快照也有它的局限性。它拍的是一张内存的“大合影”,不可避免地会耗时耗力。虽然,Redis设计了bgsave和写时复制方式,尽可能减少了内存快照对正常读写的影响,但是,频繁快照仍然是不太能接受的。而混合使用RDB和AOF,正好可以取两者之长,避两者之短,以较小的性能开销保证数据可靠性和性能。

最后,关于AOF和RDB的选择问题,我想再给你提三点建议:

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
img

总结

虽然面试套路众多,但对于技术面试来说,主要还是考察一个人的技术能力和沟通能力。不同类型的面试官根据自身的理解问的问题也不尽相同,没有规律可循。

上面提到的关于这些JAVA基础、三大框架、项目经验、并发编程、JVM及调优、网络、设计模式、spring+mybatis源码解读、Mysql调优、分布式监控、消息队列、分布式存储等等面试题笔记及资料

有些面试官喜欢问自己擅长的问题,比如在实际编程中遇到的或者他自己一直在琢磨的这方面的问题,还有些面试官,尤其是大厂的比如 BAT 的面试官喜欢问面试者认为自己擅长的,然后通过提问的方式深挖细节,刨根到底。
ybatis源码解读、Mysql调优、分布式监控、消息队列、分布式存储等等面试题笔记及资料**

有些面试官喜欢问自己擅长的问题,比如在实际编程中遇到的或者他自己一直在琢磨的这方面的问题,还有些面试官,尤其是大厂的比如 BAT 的面试官喜欢问面试者认为自己擅长的,然后通过提问的方式深挖细节,刨根到底。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值