redis 启动加载mysql_Redis分析系列:启动加载过程

从本篇文章开始(命名为Redis分析系列),将会通过分析Redis的源代码(以Redis 2.2.0 RC1为准),来对它的内部实现做一些探讨。本文主要介绍Redis启动加载过程,总体上可以分为如下几步:

1. 初始化全局服务器配置

2. 加载配置文件(如果指定了配置文件,否则使用默认配置)

3. 初始化服务器

4. 加载数据库

5. 网络监听

整个启动加载过程如下图所示:

image.axd?picture=2011%2f1%2fredis001.png

下面对于上图中的各个步骤一些介绍,有些部分(如数据库加载、网络监听)会在后面单独用一篇文章详细说明。

初始化全局服务器配置

初始化全局服务器配置通过initServerConfig()函数完成,主要是初始化server变量,它是一个redisServer的结构类型:

structredisServer server;

初始化的内容包括下面几个方面:

1. 网络监听相关,如绑定地址,TCP端口等

2. 虚拟内存相关,如swap文件、page大小等

3. 保存机制,多长时间内有多少次更新才进行保存

4. 复制相关,如是否是slave,master地址、端口

5. Hash相关设置

6. 初始化命令表

如其中的保存机制中,服务器初始化策略为:

// 1小时内1次更新appendServerSaveParams(60*60,1);

// 5分钟内100次更新appendServerSaveParams(300,100);

// 1分钟内10000次更新appendServerSaveParams(60,10000);

如果在启动服务器时,指定了配置文件,则会在下面的“加载配置文件”步骤中,根据配置文件内容,更改其中的某些服务器配置。

加载配置文件

如果指定了配置文件,Redis使用loadServerConfig()函数加载配置文件,整个过程没什么可以说的,无非是使用标准I/O库打开配置文件,循环读取每一行然后覆盖上一步进行的默认配置。

这里有一点需要注意的是,下载Redis后代码包中有一个默认配置文件,如果启动Redis服务器时,不指定配置文件,Redis不会使用这个默认文件的配置,而是使用上一步“初始化全局服务器配置”中的配置。在默认配置文件中提供的配置项与上一步默认初始化的配置有些事不一样的,所以如果没有指定配置文件,千万不能认为Redis的行为会按照默认配置文件进行,最典型的一个例子,在默认配置文件中的数据保存策略是:

#15分钟内1次更新

save 900 1

#5分钟内100次更新

save 300 10

#1分钟内10000次更新

save 60 10000

而默认初始化的全局配置中数据保存策略:

// 1小时内1次更新appendServerSaveParams(60*60,1);

// 5分钟内100次更新appendServerSaveParams(300,100);

// 1分钟内10000次更新appendServerSaveParams(60,10000);

初始化服务器

初始化服务器的工作在initServer()函数中,主要是完成前面未完成的工作,继续对server变量初始化,如设置信号处理、创建clients、slaves列表,创建Pub/Sub通道列表,同时还会创建共享对象:

shared.crlf= createObject(REDIS_STRING,sdsnew("\r\n"));

shared.ok= createObject(REDIS_STRING,sdsnew("+OK\r\n"));

shared.err= createObject(REDIS_STRING,sdsnew("-ERR\r\n"));

shared.emptybulk= createObject(REDIS_STRING,sdsnew("$0\r\n\r\n"));

最后,如果启用了虚拟内存机制,还需要初始化虚拟内存相关,如Thread I/O等。

加载数据库

在完成了上面的所有的初始化工作之后,Redis开始加载数据到内存中,如果启用了appendonly了(不知道这个参数做什么的,请先看配置文件篇),则Redis从appendfile加载数据,否则就从dbfile加载数据。

1. 从appendfile中加载数据:loadAppendOnlyFile()函数

在此之前,我们先来看一下appendfile里面保存了什么,如我执行了下面两条命令(记得在配置文件中开启appendonly):

redis> SET mykey001 myvalue001

OK

redis> GET mykey001

"myvalue001"

使用cat命令查看appendonly.aof文件内容:

$ cat appendonly.aof

*2

$6

SELECT

$1

0

*3

$3

SET

$8

mykey001

$10

myvalue001

嗯,相信大家都能看明白(看不明白的请先看这篇文章),在appendonly.aof文件中保存的正是从客户端发过来的请求命令,还可以看到对于GET命令,并没有保存。既然appendonly.aof中保存了所有写入数据的请求命令,那么在加载数据的时候只要重新执行一遍这些命令即可。

事实上Redis也正是这么做的,在开始加载之前暂时关闭appendonly,然后Redis创建一个假的Redis客户端:

server.appendonly= 0;

fakeClient = createFakeClient();

startLoading(fp);

然后读取appendonly.aof文件中的命令,在假的Redis客户端上下文中执行,同时服务器也不对该客户端做任何应答:

fakeClient->argc= argc;

fakeClient->argv= argv;

cmd->proc(fakeClient);

/* The fake client should not have a reply */redisAssert(fakeClient->bufpos== 0 && listLength(fakeClient->reply) == 0);

如果加载过程中物理内存不够用,并且Redis开启了VM,则还需要处理swap操作,最后加载完成后重新设置appendonly标志。

2. 从dbfile中加载数据:rdbLoad()函数

如果Redis没有开启appendonly,就需要从数据库文件中加载数据到内存,基本步骤如下:

a. 处理SELECT命令,即选择数据库

b. 读取key

c. 读取value

d. 检测key是否过期

e. 添加新的对象到哈希表

f. 设置过期时间(如果需要)

g. 如果开启了VM,处理swap操作

网络监听

在完成了初始化配置和数据加载后,Redis启动监听。Redis的网络库没有使用libevent或者libev,而是作者自己实现的一个非常轻量级的库(主要实现在ae.c文件中),这部分内容在后面分析Redis的网络库的时候单独写篇文章。

通过本文,介绍了Redis的启动加载过程,希望对大家有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338377.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c 文件怎么进行读取和写入操作?

C >>和<<读写文本文件&#xff1a;fstream 或者 ifstream 类负责实现对文件的读取&#xff0c;它们内部都对 >> 输出流运算符做了重载&#xff1b;同样&#xff0c;fstream 和 ofstream 类负责实现对文件的写入&#xff0c;它们的内部也都对 << 输出流…

mysql+误操作怎么恢复_Mysql误操作恢复流程

一、开启binlog。show variables like log_bin;#vim /etc/my.cnf在[mysqld]中加入log-bin mysql-binlog-bin /usr/local/mysql/log/mysql-bin.log重启mysql服务#service mysqld stop#service mysqld start二、数据写入建库create database …

drools6.5_Drools 6.2.0.Final发布

drools6.5我们很高兴地宣布最新&#xff0c;最出色的Drools 6.2.0.Final版本。 特别是此发行版更加注重改进的可用性和功能&#xff0c;这些功能使项目更易于使用&#xff08;和采用&#xff09;。 新功能包括对工作台UI的大量改进&#xff0c;对社交活动和插件管理的支持以及…

c程序编写x的y次方的方法

c程序怎么编写x的y次方?C语言pow()函数&#xff1a;求x的y次方&#xff08;次幂&#xff09;头文件&#xff1a;#include pow() 函数用来求 x 的 y 次幂&#xff08;次方&#xff09;&#xff0c;其原型为&#xff1a;double pow(double x, double y);pow()用来计算以x 为底的…

8条嵌入式C语言编程小知识总结

1. 流水线被指令填满时才能发挥最大效能&#xff0c;即每时钟周期完成一条指令的执行(仅指单周期指令)。如果程序发生跳转&#xff0c;流水线会被清空&#xff0c;这将需要几个时钟才能使流水线再次填满。因此&#xff0c;尽量少的使用跳转指令可以提高程序执行效率&#xff0c…

c语言函数的三种调用方式是什么?

函数的三种调用方式&#xff1a;1、函数作为表达式中的一项出现在表达式中&#xff0c;例“zmax(x,y)”&#xff1b;2、函数作为一个单独的语句&#xff0c;例“printf("%d",a)”&#xff1b;3、函数作为调用另一个函数时的实参&#xff0c;例“printf("%d"…

弱口令扫描工具mysql ftp_基于端口的弱口令检测工具--iscan

iscan: 基于端口的弱口令检测工具亲手打造了一款基于端口的弱口令检测工具&#xff0c;使用python进行编写&#xff0c;主要可以用于渗透测试中常见服务端口弱口令的检测。目前支持以下服务&#xff1a;系统弱口令&#xff1a;ftp、ssh、telnet、ipc$数据库弱口令&#xff1a;m…

javafx 剪切板_JavaFX技巧18:路径剪切

javafx 剪切板我最近注意到&#xff0c;我致力于ControlsFX项目的PopOver控件无法正确剪切其内容。 当我为FlexCalendarFX框架开发手风琴弹出窗口时&#xff0c;这一点变得显而易见。 每当最后一个标题窗格扩展时&#xff0c;其底角不再是圆角而是正方形。 在标题窗格中放置一个…

嵌入式开发中C语言编程要点简述!

在嵌入式Linux的C语言开发中&#xff0c;C语言的基本编程依然是最重要的内容。除此之外&#xff0c;与一般的C语言编程相比&#xff0c;嵌入式Linux的C语言编程有以下一些要点&#xff1a;1、库函数与系统调用在进行C语言编程的时候&#xff0c;使用库函数是不可避免的。关于使…

C语言中,break和continue都是跳出循环,有啥区别?

首先说明&#xff1a;continue 只能用于循环语句中&#xff0c;而break可用于循环和 switch 语句&#xff0c;两者都是辅助循环&#xff1b;尽管如此&#xff0c;如果 switch 语句在一个循环中&#xff0c;continue便可作为 switch 语句的一部分&#xff1b;这种情况下&#xf…

C 的 3种内存顺序,你都知道吗?

1、std::memory_order_relaxed “自由”内存顺序在原子类型上的操作以自由序列执行&#xff0c;没有任何同步关系&#xff0c;仅对此操作要求原子性。例如&#xff0c;在某一线程中&#xff0c;先写入A&#xff0c;再写入B。但是在多核处理器中观测到的顺序可能是先写入B&#…

C 常见的面试知识点(上)

const 作用1&#xff0c;修饰变量&#xff0c;说明该变量不可以被改变2&#xff0c;修饰指针&#xff0c;分为指向常量的指针&#xff08;pointer to const&#xff09;和自身是常量的指针&#xff08;常量指针&#xff0c;const pointer&#xff09;3&#xff0c;修饰引用&…

C 常见的面试知识点(下)

inline 内联函数的特征相当于把内联函数里面的内容写在调用内联函数处&#xff1b;相当于不用执行进入函数的步骤&#xff0c;直接执行函数体&#xff1b;相当于宏&#xff0c;却比宏多了类型检查&#xff0c;真正具有函数特性&#xff1b;编译器一般不内联包含循环、递归、swi…

php cdi_集成CDI和WebSockets

php cdi考虑尝试一个简单的Java EE 7原型应用程序&#xff0c;该应用程序涉及JAX-RS&#xff08;REST&#xff09;&#xff0c;WebSockets和CDI。 注意 &#xff1a;不想让它成为破坏者-但本文主要讨论我在尝试使用Web套接字和使用CDI作为“胶水”&#xff08;在Java EE应用程…

c语言排序方法有哪几种?

c语言排序方法有&#xff1a;1、简单选择排序&#xff0c;基于O&#xff08;n2&#xff09;时间复杂度的排序算法&#xff1b;2、冒泡排序&#xff1b;3、简单插入排序&#xff1b;4、希尔排序&#xff1b;5、归并排序&#xff0c;基于归并操作的一种排序算法&#xff1b;6、快…

java 类型不可视_jvm高级特性(5)(1)(原子性,可见性,有序性,volatile,概述)

简介&#xff1a;阿姆达尔定律(Amdahl)&#xff1a;该定律通过系统中并行化与串行化的比重来描述多处理器系统能获得的运算加速能力。摩尔定律(Moore)&#xff1a;该定律用于描述处理器晶体管数量与运行效率间的发展关系。当价格不变时&#xff0c;集成电路上可容纳的元器件的数…

c语言怎么输入3个数输出最大值

方法&#xff1a;首先使用scanf()接收从键盘输入的三个数&#xff1b;然后使用“if else”语句比较三个数的大小&#xff0c;获得最大值&#xff1b;最后使用print()函数将最大值输出即可。c语言输入3个数输出最大值#include int main() { // 输入abc输出最大值 int a; …

java调用ecdh_椭圆曲线ECC ECDH原理 javacard实现

椭圆曲线原理&#xff1a;椭圆曲线的图像并不是椭圆形&#xff0c;椭圆曲线源自于求椭圆弧长的椭圆积分的反函数。定义&#xff1a;椭圆曲线可用下列方程来表示&#xff0c;其中a,b,c,d为系数。E&#xff1a; y2 ax3 bx2 cx d椭圆曲线运算&#xff1a;(相当于交换群)AB&#x…

C 常用新特性(上)

下面是正文&#xff1a;auto类型推导auto可以让编译器在编译器就推导出变量的类型&#xff0c;看代码&#xff1a;利用auto可以通过右边的类型推导出变量的类型。什么时候使用auto呢&#xff1f;简单类型其实没必要使用auto&#xff0c;然而某些复杂类型就有必要使用auto&#…

c编译程序是什么?

c编译程序是由计算机厂家提供的一套软件。c编译程序又称c语言编译器&#xff0c;是指用c语言书写的源程序&#xff0c;翻译成等价的机器语言格式目标程序的翻译程序。编译程序属于采用生成性实现途径实现的翻译程序。它以高级程序设计语言书写的源程序作为输入&#xff0c;而以…