当前位置: 首页 > news >正文

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

AOF的回顾

         回顾Redis 的AOF的持久化机制。 Redis 避免数据丢失的 AOF 方法。这个方法的好处,是每次执行只需要记录操作命令,需要持久化的数据量不大。一般而言,只要你采用的不是 always 的持久化策略,就不会对性能造成太大影响。

        但是,也正因为记录的是操作命令,而不是实际的数据,所以,用 AOF 方法进行故障恢复
的时候,需要逐一把操作日志都执行一遍。如果操作日志非常多,Redis 就会恢复得很缓
慢,影响到正常使用。那这就引出了这篇文章所写的:内存快照。所谓内存快照,就是指内存中的数据在某一个时刻的状态记录。

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

        和 AOF 相比,RDB 记录的是某一时刻的数据,并不是操作,这样恢复数据会很快,那为啥不直接把RDB作为最优选呢?

        我们需要考虑两件事情:

        对哪些数据做快照?这关系到快照的执行效率问题;
        做快照时,数据还能被增删改吗?这关系到 Redis 是否被阻塞,能否同时正常处理请求。

给哪些内存数据做快照?

        Redis 的数据都在内存中,为了提供所有数据的可靠性保证,它执行的是全量快照,也就
是说,把内存中的所有数据都记录到磁盘中,这就类似于给 100 个人拍合影,把每一个人
都拍进照片里。这样做的好处是,一次性记录了所有数据,一个都不少。

        当你给一个人拍照时,只用协调一个人就够了,但是,拍 100 人的大合影,却需要协调
100 个人的位置、状态,等等,这当然会更费时费力。同样,给内存的全量数据做快照,
把它们全部写入磁盘也会花费很多时间。而且,全量数据越多,RDB 文件就越大,往磁盘
上写数据的时间开销就越大。

        对于 Redis 而言,它的单线程模型就决定了,我们要尽量避免所有会阻塞主线程的操作,
所以,针对任何操作,我们都会提一个灵魂之问:“它会阻塞主线程吗?”RDB 文件的生成
是否会阻塞主线程,这就关系到是否会降低 Redis 的性能。

        Redis 提供了两个命令来生成 RDB 文件,分别是 save 和 bgsave

        save:在主线程中执行,会导致阻塞;
        bgsave:创建一个子进程,专门用于写入 RDB 文件,避免了主线程的阻塞,这也是
        Redis RDB 文件生成的默认配置。

好了,这个时候,我们就可以通过 bgsave 命令来执行全量快照,这既提供了数据的可靠
性保证,也避免了对 Redis 的性能影响。

接下来,我们要关注的问题就是,在对内存数据做快照时,这些数据还能“动”吗? 也就是
说,这些数据还能被修改吗? 这个问题非常重要,这是因为,如果数据能被修改,那就意
味着 Redis 还能正常处理写操作。否则,所有写操作都得等到快照完了才能执行,性能一
下子就降低了。

快照时数据能修改吗?

在给别人拍照时,一旦对方动了,那么这张照片就拍糊了,我们就需要重拍,所以我们当
然希望对方保持不动。对于内存快照而言,我们也不希望数据“动”。

举个例子。我们在时刻 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),在执行快照的同时,正常处理写操作。

简单来说,bgsave 子进程是由主线程 fork 生成的,可以共享主线程的所有内存数据。
bgsave 子进程运行后,开始读取主线程的内存数据,并把它们写入 RDB 文件。

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

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

到这里,我们就解决了对“哪些数据做快照”以及“做快照时数据能否修改”这两大问
题:Redis 会使用 bgsave 对当前内存中的所有数据做快照,这个操作是子进程在后台完
成的,这就允许主线程同时可以修改数据。
现在,我们再来看另一个问题:多久做一次快照?我们在拍照的时候,还有项技术叫“连
拍”,可以记录人或物连续多个瞬间的状态。那么,快照也适合“连拍”吗?

可以每秒做一次快照吗?

连拍的间隔比较大的话就是你当及两次拍照的之间发生宕机的话,丢失的数据就会很多。

但是如果连拍间隔非常小的话,虽然 bgsave 执行时不阻塞主线程,但是,如果频繁地执行全量
快照,也会带来两方面的开销。:

一方面,频繁将全量数据写入磁盘,会给磁盘带来很大压力,多个快照竞争有限的磁盘带
宽,前一个快照还没有做完,后一个又开始做了,容易造成恶性循环。

另一方面,bgsave 子进程需要通过 fork 操作从主线程创建出来。虽然,子进程在创建后
不会再阻塞主线程,但是,fork 这个创建过程本身会阻塞主线程,而且主线程的内存越
大,阻塞时间越长。如果频繁 fork 出 bgsave 子进程,这就会频繁阻塞主线程了。那么,
有什么其他好方法吗?

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

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

 但是我们两次拍照之间有1万键值对别更改了。但是存出这个增量的空间很有效。所以这个增量的只适用于修改次数少的。

到这里,你可以发现,虽然跟 AOF 相比,快照的恢复速度快,但是,快照的频率不好把
握,如果频率太低,两次快照间一旦宕机,就可能有比较多的数据丢失。如果频率太高,
又会产生额外开销,那么,还有什么方法既能利用 RDB 的快速恢复,又能以较小的开销做
到尽量少丢数据呢

AOF和RDB混合使用

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

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

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

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

相关文章:

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

AOF的回顾 回顾Redis 的AOF的持久化机制。 Redis 避免数据丢失的 AOF 方法。这个方法的好处,是每次执行只需要记录操作命令,需要持久化的数据量不大。一般而言,只要你采用的不是 always 的持久化策略,就不会对性能造成太大影响。 …...

Linux之 Ubuntu 安装常见服务 (二) Tomcat

安装TomCat 服务 1、安装JDK环境 https://www.oracle.com/java/technologies/downloads/ 下载的官网 wget https://download.oracle.com/java/20/latest/jdk-20_linux-x64_bin.deb (sha256) 使用dpkg进行软件安装时,提示:dpkg:处理软件包XX…...

docker 配置 Mysql主从集群

Docker version 20.10.17, build 100c701 MySQL Image version: 8.0.32 Docker container mysql-master is source. mys ql-replica is replication. master source. replica slave.名称叫法不一样而已。 Choose one of the way,与replica同步数据两种情况&…...

Layui实现OA会议系统之会议管理模块总合

目录 一、项目背景 二、项目概述 1. 概述 2. 环境搭建 3. 工具类引用 4. 功能设计 4.1 会议发布 4.2 我的会议 4.3 会议审批 4.4 会议通知 4.5 待开会议 4.6 历史会议 4.7 所有会议 5. 性能优点 5.1 兼容性好 5.2 可维护性和可扩展性 5.3 轻量灵活 5.4 模块化设计…...

fishing之踩坑篇捕获数据不齐全

文章目录 一、问题记录二、解决方法三、更新钓鱼模板四、进行点击邮件五、查看仪表盘免责声明 一、问题记录 通过点击邮件内的链接,提交数据,但是只记录密码,无法记录username 二、解决方法 对于需要被捕获的表单数据,除了inp…...

ppt使用笔记

文章目录 如何让文档好看纯文字绝对不可行多用流程图和效果图切换动画母版音乐视频 作品渐变星空放大镜随机抽奖 其他快捷键 作为一个开发,对这种表现类型的软件一直不太上心,但有些场景要用到ppt,例如述职和项目案例分享。 很直观的体验就是…...

java中的hashmap和concurrenthashmap解析

hashmap的初始化数组大小为16,如果发生哈希冲突的时候在当前的索引后面采用头插法以链表的形式继续插入节点。 concurrenthashmap的结构图如下所示: 本身不是16个节点吗?这里分为两个长度为4的数组,变成了4*4总共16个节点&#x…...

元素2D转3D 椭圆形旋转实现

椭圆旋转功能展示 transform-style: preserve-3d;(主要css代码) gif示例(背景图可插入透明以此实现边框线的旋转) 导致的无法点击遮挡问题可以参考我的另一个文章 穿透属性-----------------------css穿透属性 实时代码展示...

Centos7.9 制作openssh9.2p2 rpm升级包和升级实战

一、背景说明 Centos7.9 默认安装的openssh 版本为7.4p1,经绿盟扫描,存在高危漏洞,需要升级到最新。 官网只提供编译安装包,为了方便升级,先通过编译安装包,制作rpm包,并进行升级 如下为做好…...

JavaScript学习(3)

Web API 是开发人员的梦想。 它可以扩展浏览器的功能它可以极大简化复杂的功能它可以为复杂的代码提供简单的语法 什么是 Web API? API 指的是应用程序编程接口(Application Programming Interface)。 Web API 是 Web 的应用程序编程接口…...

2023华为OD机试真题Java实现【寻找最大价值的矿堆/深度优先搜索】

前言 本题使用Java实现,如果需要Python代码,请点击以下链接 点我 题目 我们规定,0表示空地,1表示银矿、2表示金矿,矿堆表示由相邻的金矿或银矿连接形成的地图。 银矿价值是1 ,金矿价值是2 ,你的目标是找出地图中最大价值的矿堆,并且输出该矿堆的价值 示例1 输入:…...

MyCat概述

1.MyCat概述 MyCat是阿里巴巴的产品,他是开源的、基于Java语言编写的MySQL数据库中间件。可以像使用mysql一样来使用mycat,对于开发人员来说根本感觉不到mycat的存在。 MyCat下载地址:http://dl.mycat.org.cn/ MyCat官网:http:/…...

【LeetCode】【数据结构】单链表OJ常见题型(一)

👀樊梓慕:个人主页 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》 🌝每一个不曾起舞的日子,都是对生命的辜负。 目录 前言: 【LeetCode】203.移除链表元素 【LeetCo…...

QGraphicsView实现简易地图3『局部加载-地图缩放』

前文链接:QGraphicsView实现简易地图2『瓦片经纬度』 第一篇文章提到过,当地图层级较大时,暴力全加载地图会造成程序卡顿,因此需要实现地图的局部加载。 实现思路:以地图窗口(以下称为视口)为地…...

bash的特性(二)IO重定向与管道

bash的I/O重定向及管道 一、概述 在shell中,最常使用的fd(file descriptor)有三个,标准输入,标准输出,错误输出。进程用文件描述符来管理打开的文件。 名称 文件描述符 标准输入(stdin) 0 键盘,也可以…...

elb 直接配置到后端服务器组

出现上图报错的原因是,前面elb配置了https证书,后端的nginx也配置了证书,导致冲突。 需要修改后端的nginx配置文件,将证书配置注释掉。 如果出现健康检查异常,需要在对应服务器的安全组上配置elb所在的网段的访问权限…...

安卓:BottomNavigationBar——底部导航栏控件

目录 一、BottomNavigationBar介绍 二、BottomNavigationBar的常用方法及其常用类 (一)、常用方法 1. 添加菜单项 2. 移除菜单项 3. 设置选中监听器 4. 设置当前选中项 5. 设置徽章 6. 样式和颜色定制 7. 动画效果 8. 隐藏底部导航栏。 9、设…...

十、用 ChatGPT 辅助写文章

目录 一、实验介绍 二、背景 三、ChatGPT 写作方式 3.1 传统写作方式 3.2 ChatGPT 写作方式...

计算机毕设 深度学习猫狗分类 - python opencv cnn

文章目录 0 前言1 课题背景2 使用CNN进行猫狗分类3 数据集处理4 神经网络的编写5 Tensorflow计算图的构建6 模型的训练和测试7 预测效果8 最后 0 前言 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往…...

60多行代码仿制B站首页一个好看的卡片效果

文章目录 1、为啥是这个?2、仿制效果3、实现思路4、代码5、查看B站如何实现 1、为啥是这个? 看到Bilibili首页的一个卡片,看着效果很不错,给人很舒适的感觉。一琢磨貌似也不难,甚至只需要一层 div 就可以实现主要框架…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

深度解析:etcd 在 Milvus 向量数据库中的关键作用

目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...

Selenium 查找页面元素的方式

Selenium 查找页面元素的方式 Selenium 提供了多种方法来查找网页中的元素,以下是主要的定位方式: 基本定位方式 通过ID定位 driver.find_element(By.ID, "element_id")通过Name定位 driver.find_element(By.NAME, "element_name"…...

【动态规划】B4336 [中山市赛 2023] 永别|普及+

B4336 [中山市赛 2023] 永别 题目描述 你做了一个梦,梦里有一个字符串,这个字符串无论正着读还是倒着读都是一样的,例如: a b c b a \tt abcba abcba 就符合这个条件。 但是你醒来时不记得梦中的字符串是什么,只记得…...

开源 vGPU 方案:HAMi,实现细粒度 GPU 切分

本文主要分享一个开源的 GPU 虚拟化方案:HAMi,包括如何安装、配置以及使用。 相比于上一篇分享的 TimeSlicing 方案,HAMi 除了 GPU 共享之外还可以实现 GPU core、memory 得限制,保证共享同一 GPU 的各个 Pod 都能拿到足够的资源。…...