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

Redis rdb源码解析

   前置学习:Redis server启动源码-CSDN博客

1、触发时机

        1、执行save命令--->rdbSave函数

        2、执行bgsave命令--->rdbSaveBackground函数或者(serverCron->prepareForShutdown)

        3,主从复制-->startBgsaveForReplication函数,落盘方式(rdbSaveBackground函数),不落盘方式(rdbSaveToSlavesSockets函数)。

        4、flushall命令--->flushallCommand函数

        5、正常关闭服务(serverCron->prepareForShutdown函数)

2、执行过程

在主进程(父进程)中fork一个子进程来生成rdb文件(二进制),父子进程通过管道来处理数据传输通信。

 生成RDB文件过程

/* Save the DB on disk. Return REDIS_ERR on error, REDIS_OK on success ** 将数据库保存到磁盘上。** 保存成功返回 REDIS_OK ,出错/失败返回 REDIS_ERR 。*/
int rdbSave(char *filename) {dictIterator *di = NULL;dictEntry *de;char tmpfile[256];char magic[10];int j;long long now = mstime();FILE *fp;rio rdb;uint64_t cksum;// 创建临时文件snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());fp = fopen(tmpfile,"w");if (!fp) {redisLog(REDIS_WARNING, "Failed opening .rdb for saving: %s",strerror(errno));return REDIS_ERR;}// 初始化 I/OrioInitWithFile(&rdb,fp);// 设置校验和函数if (server.rdb_checksum)rdb.update_cksum = rioGenericUpdateChecksum;// 写入 RDB 版本号(魔数)snprintf(magic,sizeof(magic),"REDIS%04d",REDIS_RDB_VERSION);if (rdbWriteRaw(&rdb,magic,9) == -1) goto werr;// 遍历所有数据库for (j = 0; j < server.dbnum; j++) {// 指向数据库redisDb *db = server.db+j;// 指向数据库键空间dict *d = db->dict;// 跳过空数据库if (dictSize(d) == 0) continue;// 创建键空间迭代器di = dictGetSafeIterator(d);if (!di) {fclose(fp);return REDIS_ERR;}/* Write the SELECT DB opcode ** 写入 DB 选择器*/if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_SELECTDB) == -1) goto werr;if (rdbSaveLen(&rdb,j) == -1) goto werr;/* Iterate this DB writing every entry ** 遍历数据库,并写入每个键值对的数据*/while((de = dictNext(di)) != NULL) {sds keystr = dictGetKey(de);robj key, *o = dictGetVal(de);long long expire;// 根据 keystr ,在栈中创建一个 key 对象initStaticStringObject(key,keystr);// 获取键的过期时间expire = getExpire(db,&key);// 保存键值对数据if (rdbSaveKeyValuePair(&rdb,&key,o,expire,now) == -1) goto werr;}dictReleaseIterator(di);}di = NULL; /* So that we don't release it again on error. *//* EOF opcode ** 写入 EOF 代码*/if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_EOF) == -1) goto werr;/* CRC64 checksum. It will be zero if checksum computation is disabled, the* loading code skips the check in this case. ** CRC64 校验和。** 如果校验和功能已关闭,那么 rdb.cksum 将为 0 ,* 在这种情况下, RDB 载入时会跳过校验和检查。*/cksum = rdb.cksum;memrev64ifbe(&cksum);rioWrite(&rdb,&cksum,8);/* Make sure data will not remain on the OS's output buffers */// 冲洗缓存,确保数据已写入磁盘if (fflush(fp) == EOF) goto werr;if (fsync(fileno(fp)) == -1) goto werr;if (fclose(fp) == EOF) goto werr;/* Use RENAME to make sure the DB file is changed atomically only* if the generate DB file is ok. ** 使用 RENAME ,原子性地对临时文件进行改名,覆盖原来的 RDB 文件。*/if (rename(tmpfile,filename) == -1) {redisLog(REDIS_WARNING,"Error moving temp DB file on the final destination: %s", strerror(errno));unlink(tmpfile);return REDIS_ERR;}// 写入完成,打印日志redisLog(REDIS_NOTICE,"DB saved on disk");// 清零数据库脏状态server.dirty = 0;// 记录最后一次完成 SAVE 的时间server.lastsave = time(NULL);// 记录最后一次执行 SAVE 的状态server.lastbgsave_status = REDIS_OK;return REDIS_OK;werr:// 关闭文件fclose(fp);// 删除文件unlink(tmpfile);redisLog(REDIS_WARNING,"Write error saving DB on disk: %s", strerror(errno));if (di) dictReleaseIterator(di);return REDIS_ERR;
}

相关文章:

Redis rdb源码解析

前置学习&#xff1a;Redis server启动源码-CSDN博客 1、触发时机 1、执行save命令--->rdbSave函数 2、执行bgsave命令--->rdbSaveBackground函数或者&#xff08;serverCron->prepareForShutdown&#xff09; 3&#xff0c;主从复制-->startBgsaveForReplication…...

深入理解CyclicBarrier

文章目录 1. 概念2. CylicBarier使用简单案例3. 源码 1. 概念 CyclicBarrier 字面意思回环栅栏&#xff08;循环屏障&#xff09;&#xff0c;通过它可以实现让一组线程等待至某个状态&#xff08;屏障点&#xff09;之后再全部同时执行。叫做回环是因为当所有等待线程都被释放…...

微信小程序 - 格式化操作 moment.js格式化常用使用方法总结大全

格式化操作使用 1. 首先&#xff0c;下载一个第三方库 moment npm i moment --save 注&#xff1a;在微信小程序中无法直接npm 下载 导入 的&#xff08;安装一个就需要构建一次&#xff09; 解决&#xff1a;菜单栏 --> 工具 --> 构建 npm 点击即可&#xff08;会…...

学习pytorch18 pytorch完整的模型训练流程

pytorch完整的模型训练流程 1. 流程1. 整理训练数据 使用CIFAR10数据集2. 搭建网络结构3. 构建损失函数4. 使用优化器5. 训练模型6. 测试数据 计算模型预测正确率7. 保存模型 2. 代码1. model.py2. train.py 3. 结果tensorboard结果以下图片 颜色较浅的线是真实计算的值&#x…...

电子学会C/C++编程等级考试2021年09月(五级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:抓牛 农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式: 1、从X移动到X-1或X+1,每次移动花费一分钟 2、从X移动到2*X,每…...

Halcon联合winform显示以及处理

在窗口中添加窗体和按钮&#xff0c;并在解决方案资源管理器中调加了导入Halcon导出的.cs文件&#xff0c;运行出现下图的问题&#xff1a; 问题1&#xff1a;CS0017 程序定义了多个入口点。使用/main(指定包含入口点的类型&#xff09;进行编译。 解决方案1.&#xff1a; 右…...

【设计模式-4.3】行为型——责任链模式

说明&#xff1a;本文介绍设计模式中行为型设计模式中的&#xff0c;责任链模式&#xff1b; 审批流程 责任链模式属于行为型设计模式&#xff0c;关注于对象的行为。责任链模式非常典型的案例&#xff0c;就是审批流程的实现。如一个报销单的审批流程&#xff0c;根据报销单…...

单片机语言--C51语言的数据类型以及存储类型以及一些基本运算

C51语言 本文主要涉及C51语言的一些基本知识&#xff0c;比如C51语言的数据类型以及存储类型以及一些基本运算。 文章目录 C51语言一、 C51与标准C的比较二、 C51语言中的数据类型与存储类型2.1、C51的扩展数据类型2.2、数据存储类型 三、 C51的基本运算3.1 算术运算符3.2 逻辑…...

《每天一个Linux命令》 -- (5)通过sshkey密钥登录服务器

欢迎阅读《每天一个Linux命令》系列&#xff01;在本篇文章中&#xff0c;将介绍通过密钥生成&#xff0c;使用公钥连接管理服务器。 概念 SSH 密钥是用于安全地访问远程服务器的一种方法。SSH 密钥由一对密钥组成&#xff1a;公钥和私钥。公钥存储在远程服务器上&#xff0c;…...

kubernetes的服务发现(二)

如前面的文章我们说了&#xff0c;kubernetes的服务发现是服务端发现模式。它有一个服务注册中心&#xff0c;使用DNS作为服务的注册表。每个集群都会运行一个DNS服务&#xff0c;默认是CoreDNS服务。每个服务都会在这个DNS中注册。注册的大致过程&#xff1a; 1、向kube-apise…...

【矩阵论】Chapter 4—特征值和特征向量知识点总结复习

文章目录 1 特征值和特征向量2 对角化3 Schur定理和正规矩阵4 Python求解 1 特征值和特征向量 定义 设 σ \sigma σ为数域 F F F上线性空间 V V V上的一个线性变换&#xff0c;一个非零向量 v ∈ V v\in V v∈V&#xff0c;如果存在一个 λ ∈ F \lambda \in F λ∈F使得 σ (…...

Linux 进程地址空间

知识回顾 在 C 语言的学习过程中&#xff0c;我们知道内存是可以被划分为栈区&#xff0c;堆区&#xff0c;全局数据区&#xff0c;字符常量区&#xff0c;代码区的。他的空间排布可能是下面的样子&#xff1a; 其中&#xff0c;全局数据区&#xff0c;可以划分为已初始化全局…...

websocket vue操作

let websocket: WebSocket; /** websocket测试 */ function connectWebsocket() {if (typeof WebSocket "undefined") {console.log("您的浏览器不支持WebSocket");return;}// let ip window.location.hostname ":8080";let ip "10.192…...

腾讯云CentOS8 jenkins war安装jenkins步骤文档

腾讯云CentOS8 jenkins war安装jenkins步骤文档 一、安装jdk 1.1 上传jdk-11.0.20_linux-x64_bin.tar.gz 1.2 解压jdk安装包文件 tar -zxvf jdk*.tar.gz 1.3 在/usr/local 目录下创建java目录 cd /usr/local mkdir java 1.4 切到java目录&#xff0c;把jdk解压文件改名为jd…...

Linux: glibc: net/if.h vs linux/if.h

最近看到一段代码改动,用net/if.h替换了linux/if.h。仔细看了看这两个的区别: https://stackoverflow.com/questions/20082433/what-is-the-difference-between-linux-if-h-and-net-if-h 从网上搜了一下看到如下的一个编译错误,如果同时使用这两个if.h文件,需要将net/if.h…...

使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题

文章目录 一、 篇头二、 操作步骤2.1 编译AOSP AS工程文件2.2 将AOSP导入Android Studio2.3 切到Project试图2.4 等待index结束2.5 下载缺失的JDK 1.82.6 导入完成 三、 导入AS的好处3.1 本文案例演示源码编译错误AS对比同文件其余地方的调用AS错误提示依赖AS做错误修正 一、 篇…...

python random详解

文章目录 random简单示例1. 生成随机浮点数&#xff1a;2. 生成指定范围内的随机整数&#xff1a;3. 从序列中随机选择元素&#xff1a;4. 打乱序列顺序&#xff1a; 常用的方法及其解释和例子&#xff1a;1. random()&#xff1a;该方法返回一个0到1之间的随机浮点数。例如&am…...

java-两个列表进行比较,判断那些是需要新增的、删除的、和更新的

文章目录 前言两个列表进行比较&#xff0c;判断那些是需要新增的、删除的、和更新的 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实…...

【WPF.NET开发】WPF中的对话框

目录 1、消息框 2、通用对话框 3、自定义对话框 实现对话框 4、打开对话框的 UI 元素 4.1 菜单项 4.2 按钮 5、返回结果 5.1 模式对话框 5.2 处理响应 5.3 非模式对话框 Windows Presentation Foundation (WPF) 为你提供了自行设计对话框的方法。 对话框是窗口&…...

NLP项目实战01之电影评论分类

介绍&#xff1a; 欢迎来到本篇文章&#xff01;在这里&#xff0c;我们将探讨一个常见而重要的自然语言处理任务——文本分类。具体而言&#xff0c;我们将关注情感分析任务&#xff0c;即通过分析电影评论的情感来判断评论是正面的、负面的。 展示&#xff1a; 训练展示如下…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...