本文主要介绍Redis启动加载过程,总体上可以分为如下几步:

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

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

3. 初始化服务器

4. 加载数据库

5. 网络监听

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

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

struct redisServer server;

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

1. 网络监听相关,如绑定地址,TCP端口等 
2. 虚拟内存相关,如swap文件、page大小等 
3. 保存机制,多长时间内有多少次更新才进行保存 
4. 复制相关,如是否是slave,master地址、端口 
5. Hash相关设置 
6. 初始化命令表

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

// 1小时内1次更新
appendServerSaveParams(*,); // 5分钟内100次更新
appendServerSaveParams(,); // 1分钟内10000次更新
appendServerSaveParams(,);

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

2、加载配置文件

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

这里有一点需要注意的是,下载Redis后代码包中有一个默认配置文件,如果启动Redis服务器时,不指定配置文件,Redis不会使用这个默认文件的配置,而是使用上一步“初始化全局服务器配置”中的配置。

在默认配置文件中提供的配置项与上一步默认初始化的配置有些事不一样的,所以如果没有指定配置文件,千万不能认为Redis的行为会按照默认配置文件进行。

最典型的一个例子,在默认配置文件中的数据保存策略是:

# 15分钟内1次更新
save # 5分钟内100次更新
save # 1分钟内10000次更新
save

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

// 1小时内1次更新
appendServerSaveParams(*,); // 5分钟内100次更新
appendServerSaveParams(,); // 1分钟内10000次更新
appendServerSaveParams(,);

3、初始化服务器

初始化服务器的工作在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等。

4、加载数据库

在完成了上面的所有的初始化工作之后,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
*
$
SELECT
$ *
$
SET
$
mykey001
$
myvalue001

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

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

server.appendonly = ;

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 == && listLength(fakeClient->reply) == );

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

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

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

a. 处理SELECT命令,即选择数据库 
b. 读取key 
c. 读取value 
d. 检测key是否过期 
e. 添加新的对象到哈希表 
f. 设置过期时间(如果需要) 
g. 如果开启了VM,处理swap操作

5、网络监听

在完成了初始化配置和数据加载后,Redis启动监听。Redis的网络库没有使用libevent或者libev。

Redis的启动过程的更多相关文章

  1. 曹工说Redis源码(3)-- redis server 启动过程完整解析(中)

    文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis,而怎么才能懂,光看是不够的,建议跟着下面的这一篇,把环境搭建起来,后续可以自己阅读源码,或者跟着我这边一起阅读.由于 ...

  2. 曹工说Redis源码(5)-- redis server 启动过程解析,以及EventLoop每次处理事件前的前置工作解析(下)

    曹工说Redis源码(5)-- redis server 启动过程解析,eventLoop处理事件前的准备工作(下) 文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis ...

  3. 关于Redis的启动过程

    一.简介 Redis的启动也就是main函数的执行,程序的入口在redis.c中,启动流程: 1. 初始化默认服务器配置,如果是sentinel模式还需进行额外的配置 2. 修改配置文件或配置选项,这 ...

  4. 曹工说Redis源码(2)-- redis server 启动过程解析及简单c语言基础知识补充

    文章导航 Redis源码系列的初衷,是帮助我们更好地理解Redis,更懂Redis,而怎么才能懂,光看是不够的,建议跟着下面的这一篇,把环境搭建起来,后续可以自己阅读源码,或者跟着我这边一起阅读.由于 ...

  5. 【源码】Redis Server启动过程

    本文基于社区版Redis 4.0.8       1. 初始化参数配置 由函数initServerConfig()实现,具体操作就是给配置参数赋初始化值: //设置时区 setlocale(LC_CO ...

  6. redis(一)内部机制的介绍和启动过程

    redis(一)内部机制的介绍和启动过程 redis的基本介绍 redis服务端 redis客户端 redis的持久化 redis中的文件事件和时间时间 redis的启动过程 redis的基本介绍 r ...

  7. redis源码笔记(一) —— 从redis的启动到command的分发

    本作品采用知识共享署名 4.0 国际许可协议进行许可.转载联系作者并保留声明头部与原文链接https://luzeshu.com/blog/redis1 本博客同步在http://www.cnblog ...

  8. laravel启动过程简单解析

    :first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:3px ...

  9. laravel的启动过程---摘自网络博客个人学习之用

    如果没有使用过类似Yii之类的框架,直接去看laravel,会有点一脸迷糊的感觉,起码我是这样的.laravel的启动过程,也是laravel的核心,对这个过程有一个了解,有助于得心应手的使用框架,希 ...

随机推荐

  1. HTML5标签canvas制作平面图

    摘要: HTML5规范已经完成了,互联网上已经有数不清的站点使用了HTML5.从现在开始研究HTML5,本文是自己在学习canvas过程中的记录,以备后需. 历史: 这个 HTML 元素是为了客户端矢 ...

  2. html+jquery制作网页地图

    http://jvectormap.com/ <!--StartFragment --> JVectorMap 是一个显示矢量地图的jQuery插件.它使用 SVG 在Firefox 3 ...

  3. PHP 5.4 中的traits

    PHP 5.4中的traits,是新引入的特性,中文还真不知道如何准确翻译好.其实际的目的,是为了有的场合想用多继承,但PHP又没多继承,于是就发明了这样的一个东西. Traits (横向重用/多重继 ...

  4. zabbix加入TCP连接数及状态的监控

    一 监控原理: [root@ nginx]# /bin/netstat -an|awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}' TIME_WAI ...

  5. GSAP JS基础教程--认识GSAP JS

    第一次写博文呢,这次写博客是因为应一位同学的要求,写一下GSAP JS的一个小教程.为什么说小呢?因为它实际上就是小,只是一个入门级的小教程.如果你想问:“那你为什么不写详细一点呢?”,我想说,说., ...

  6. PostgreSQL存储过程(1)-基于SQL的存储过程

    什么是SQL函数? SQL函数包体是一些可执行的SQL语言.同时包含1条以上的查询,但是函数只返回最后一个查询(必须是SELECT)的结果. 除非SQL函数声明为返回void,否则最后一条语句必须是S ...

  7. 【代码审计】JTBC(CMS)_PHP_v3.0 任意文件上传漏洞分析

      0x00 环境准备 JTBC(CMS)官网:http://www.jtbc.cn 网站源码版本:JTBC_CMS_PHP(3.0) 企业版 程序源码下载:http://download.jtbc. ...

  8. fstream 和 iostream

    fstream 是对文件输入输出iostream是对屏幕上输入输出你想往文件里保存内容,或者从文件里读取内容就用fstream向屏幕输出或者从屏幕上输入,用iostream “>>”运算符 ...

  9. oracle非空不做更新

    update test set B=nvl(p1,B),C=nvl(p2,C),D=nvl(p3,D),E=nvl(p4,E) where A='good'

  10. 理解Java的反射与内省及其区别

    java的内省机制和反射机制什么区别 内省操作只针对JavaBean,只有符合JavaBean规则的类的成员才可以采用内省API进行操作....而反射则不同,一个类的所有成员都可以进行反射操作. 内省 ...