Redis 核心技术与实战
蒋德钧
中科院计算所副研究员
79224 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 53 讲
开篇词 (1讲)
实践篇 (28讲)
Redis 核心技术与实战
15
15
1.0x
00:00/00:00
登录|注册

05 | 内存快照:宕机后,Redis如何实现快速恢复?

你好,我是蒋德钧。
上节课,我们学习了 Redis 避免数据丢失的 AOF 方法。这个方法的好处,是每次执行只需要记录操作命令,需要持久化的数据量不大。一般而言,只要你采用的不是 always 的持久化策略,就不会对性能造成太大影响。
但是,也正因为记录的是操作命令,而不是实际的数据,所以,用 AOF 方法进行故障恢复的时候,需要逐一把操作日志都执行一遍。如果操作日志非常多,Redis 就会恢复得很缓慢,影响到正常使用。这当然不是理想的结果。那么,还有没有既可以保证可靠性,还能在宕机时实现快速恢复的其他方法呢?
当然有了,这就是我们今天要一起学习的另一种持久化方法:内存快照所谓内存快照,就是指内存中的数据在某一个时刻的状态记录。这就类似于照片,当你给朋友拍照时,一张照片就能把朋友一瞬间的形象完全记下来。
对 Redis 来说,它实现类似照片记录效果的方式,就是把某一时刻的状态以文件的形式写到磁盘上,也就是快照。这样一来,即使宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。这个快照文件就称为 RDB 文件,其中,RDB 就是 Redis DataBase 的缩写。
和 AOF 相比,RDB 记录的是某一时刻的数据,并不是操作,所以,在做数据恢复时,我们可以直接把 RDB 文件读入内存,很快地完成恢复。听起来好像很不错,但内存快照也并不是最优选项。为什么这么说呢?
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 核心技术与实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(129)

  • 最新
  • 精选
  • Devin
    置顶
    老师全文中都是使用的“主线程”而不是“主进程”,评论中大家有的用的是“主线程”有的是“主进程”。请问下老师为啥不是用的“主进程”?

    作者回复: Redis启动后本身是一个进程,它的主体工作(接收请求、服务请求读写数据)也是在这个进程中完成的,咱们有些同学称Redis为主进程是可以的。 同时,Redis这个进程属于单线程的进程,也就是说进程主体工作没有用多个线程来运行,所以我一般把它也称为主线程,突显它的单线程模式。 有的程序启动后,会在进程中启动多个线程来处理工作,这个时候我就不会称它为主线程了,因为没有一个线程是单独做主要工作的。 希望能解答了你的问题。

    8
    121
  • Kaito
    置顶
    2核CPU、4GB内存、500G磁盘,Redis实例占用2GB,写读比例为8:2,此时做RDB持久化,产生的风险主要在于 CPU资源 和 内存资源 这2方面: a、内存资源风险:Redis fork子进程做RDB持久化,由于写的比例为80%,那么在持久化过程中,“写实复制”会重新分配整个实例80%的内存副本,大约需要重新分配1.6GB内存空间,这样整个系统的内存使用接近饱和,如果此时父进程又有大量新key写入,很快机器内存就会被吃光,如果机器开启了Swap机制,那么Redis会有一部分数据被换到磁盘上,当Redis访问这部分在磁盘上的数据时,性能会急剧下降,已经达不到高性能的标准(可以理解为武功被废)。如果机器没有开启Swap,会直接触发OOM,父子进程会面临被系统kill掉的风险。 b、CPU资源风险:虽然子进程在做RDB持久化,但生成RDB快照过程会消耗大量的CPU资源,虽然Redis处理处理请求是单线程的,但Redis Server还有其他线程在后台工作,例如AOF每秒刷盘、异步关闭文件描述符这些操作。由于机器只有2核CPU,这也就意味着父进程占用了超过一半的CPU资源,此时子进程做RDB持久化,可能会产生CPU竞争,导致的结果就是父进程处理请求延迟增大,子进程生成RDB快照的时间也会变长,整个Redis Server性能下降。 c、另外,可以再延伸一下,老师的问题没有提到Redis进程是否绑定了CPU,如果绑定了CPU,那么子进程会继承父进程的CPU亲和性属性,子进程必然会与父进程争夺同一个CPU资源,整个Redis Server的性能必然会受到影响!所以如果Redis需要开启定时RDB和AOF重写,进程一定不要绑定CPU。

    作者回复: 除了考虑了内存风险,还考虑了CPU风险。赞!先置个顶 :D 关于绑核的操作,后面再和Kaito同学聊聊,绑核也有些值得探讨的地方的。

    117
    1002
  • Geek_Lin
    文章中写时复制那里,复制的是主线程修改之前的数据还是主线程修改之后的呢?

    作者回复: 子进程读到的是主线程修改前的数据。 我在文章中介绍写时复制时,说法上有点偏它能达到的效果了,可能让大家理解有误了,抱歉! 我再解释下,文章中说“这块数据就会被复制一份,生成该数据的副本”,这个操作在实际执行过程中,是子进程复制了主线程的页表,所以通过页表映射,能读到主线程的原始数据,而当有新数据写入或数据修改时,主线程会把新数据或修改后的数据写到一个新的物理内存地址上,并修改主线程自己的页表映射。所以,子进程读到的类似于原始数据的一个副本,而主线程也可以正常进行修改。 希望能解答你的疑惑。

    14
    85
  • 扩散性百万咸面包
    感觉老师这里是不是说的有点问题? 1.fork()本身应该是比较快的吧?因为COW的存在,只需要部分数据(局部变量)的复制。真正阻塞的是bgsave在持久化过程中写RDB的时候,因为同时要服务写请求,所以主线程要复制对应内存。 2.这个复制为什么不能让fork()出来的子线程去做呢?这样不就不阻塞主线程了吗?

    作者回复: 可以看下第10讲的答疑,有对COW的底层机制做了更加详细的介绍。 第5讲介绍COW时,有点偏于介绍COW的效果了。实际上,fork本身这个操作执行时,内核需要给子进程拷贝主线程的页表。如果主线程的内存大,页表也相应大,拷贝页表耗时长,会阻塞主线程。 bgsave保存RDB时,如果有写请求,主线程会把新数据写到新的物理地址,此时的阻塞会来自于主线程申请新内存空间以及复制原数据。 如果是子进程做复制,而主线程直接改数据的话,会有问题:1. 如果子进程还没有把一块数据写入RDB时,主线程就修改了数据,那么就快照完整性就被破坏了;2. 子进程复制数据时,也需要加锁,避免主线程同时修改,如果此时,主线程正好有写请求要处理,主线程同样会被阻塞。

    5
    38
  • yyl
    解答: 系统的QPS未知,两种情况吧: 1. QPS较低,不会有什么问题 2. QPS较高,首先由于写多读少,造成更多的写时拷贝,导致更多的内存占用。如果采用增量快照,需要增加额外的内存开销;再则,写RDB文件,OS会分配一些Cache用于磁盘写,进一步加剧内存资源的消耗。 由于频繁的写RDB文件,造成较大的磁盘IO开销,消耗CPU

    作者回复: 非常赞!考虑到了根据不同的QPS进行分析。 我再提一个维度,你可以考虑下,就是修改的键值对的范围,也就是说写操作是针对一小部分键值对,还是针对大部分键值对的。你觉得这个维度会有影响么?

    2
    20
  • 漫步oo0云端
    我想提一个傻问题,我作为初学者想问,如果redis服务挂了,备份有什么用?能恢复的前提不是服务还存活吗?难道服务挂了会自动拉起服务?自动还原吗?

    作者回复: 如果服务挂了,我们可以让Redis实例自动重启。此时,如果没有数据备份的话,再启动时,所有的数据都需要重新写入,这个过程会比较耗时。而如果有备份的话,Redis再启动后,可以直接读入备份数据,对于这些数据的读写操作就可以很快服务了。不知道有没有解答你的疑惑。 愿意提出来的问题都是好问题哈 :)

    19
    17
  • 老师,请教一下,bgsave命令只能是手动执行么?没配置中只看到了save,没有bgsave的配置

    作者回复: 可以自动执行。Redis配置文件中的save选项是用来配置bgsave的触发条件的,例如 save 60 10000 如果60s内有至少10000个键值对的修改,就会自动触发bgsave了。

    8
  • 小宇子2B
    做RDB期间是写时复制的 2GB的数据 80%都是写请求 也就是大概要复制出来1.6GB数据,加上本身数据2GB ,已经达到3.6GB,去掉操作系统本身的内存占用 机器所剩内存已经不多了 容易发生OOM

    作者回复: 分析的不错,这种情况下,内存的潜在压力风险比较大。 另外,Kaito同学还分析了CPU资源的风险,也可以看看。

    4
    8
  • 周翔在山麓(Xiang Zhou)
    这一讲真的很好, aof 相当于数据库的 binlog, rdb 相当于redo log. 知识互相映射, 加强了学习. 我又看了一遍mysql 的数据恢复机制. 同学们还记得吗?

    作者回复: 学习时把知识贯通起来理解是个好方法!

    5
    7
  • Spring4J
    由于修改操作占大部分比例,为了尽可能保证宕机时数据的完整性,快照的间隔就不能太长,而间隔太短又会带来很多的性能开销,所以对于这种特点的数据,不适合使用RDB的持久化方式

    作者回复: 不错,不错!可以再想想看,在问题里的云主机上,哪怕我们先不考虑快照频率问题,单就做一次快照本身,是否可能还会有其他问题?:)

    2
    2
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部