从本篇文章开始(命名为Redis分析系列),将会通过分析Redis的源代码(以Redis 2.2.0 RC1为准),来对它的内部实现做一些探讨。本文主要介绍Redis启动加载过程,总体上可以分为如下几步:
1. 初始化全局服务器配置
2. 加载配置文件(如果指定了配置文件,否则使用默认配置)
3. 初始化服务器
4. 加载数据库
5. 网络监听
整个启动加载过程如下图所示:
下面对于上图中的各个步骤一些介绍,有些部分(如数据库加载、网络监听)会在后面单独用一篇文章详细说明。
初始化全局服务器配置
初始化全局服务器配置通过initServerConfig()函数完成,主要是初始化server变量,它是一个redisServer的结构类型:
struct redisServer 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的启动加载过程,希望对大家有所帮助。
相关推荐
声明:此文档源自钱文品老师所著《Redis深度历险:核心原理和应用实践》,只供个人学习所用,不得私自用于商业用途Redis 深度历险:核心原理与应用实践 | 钱
Redis深度历险:核心原理和应用实践 比较稀缺的紫瑶
总结《Redis深度历险:核心原理和应用实践》的xmind图
Redis深度历险:核心原理和应用实践
通过易语言操作Redis 来自JimStone 谢栋 Redis协议客户端模块:STRedisClient
在ASP.NET MVC中使用Redis 的Demo:通过Redis实现用户登陆,并保持登陆状态,设置过期时间,检测在线用户。
它将启动 6 个 Redis 服务器,监听7000~7005端口和一个主管以确保所有服务器都启动。 在所有服务器启动后,redis-trib 将创建一个 Redis 集群。 docker run -p 7000:7000 -p 7001:7001 -p 7002:7002 -p 7003:7003 -...
redis-server:5.0.14.1 windows版本解压即用版,可以通过双击redis-start.bat启动redis服务,也可以将它发布为redis服务,方便日常开发和测试
Redis::Fast - Redis 数据库的 Perl 绑定 概要 ## Defaults to $ENV{REDIS_SERVER} or 127.0.0.1:6379 my $redis = Redis::Fast->new; my $redis = Redis::Fast->new(server => 'redis.example.com:8080'); ## Set ...
阿里云Redis的规范:键值设计、命令使用、客户端使用、相关工具.docx
Redis命名空间Redis的::命名空间提供了一个接口,您的命名空间的子集密钥空间(例如,具有共同的开始键),并要求宝石。 require 'redis-namespace'# => trueredis_connection = Redis . new# => #<Redis>namespaced...
redis-port(Linux 64 位) 是一组开源工具集合,主要用于 Redis 节点间的数据库同步、数据导入、数据导出,支持 Redis 的跨版本数据迁移。其包括以下工具: redis-sync:支持在 Redis 实例之间进行数据迁移。 redis...
Redis,典型的NoSQL数据库服务器,和BerkeleyDB相比,它可以作为服务程序独立运行于自己的服务器主机。在很多时候,人们只是将Redis视为Key/Value数据库服务器,然而事实并非如此,在目前的版本中,Redis除了Key/...
详细介绍Redis启动流程,重点参考《Redis 设计与实现》一书。
Redis系列:深刻理解高性能Redis的本质.doc
redis2.8.6的安装过程和一些错误的解决,
Redis-sentinel是Redis的作者antirez完成的,因为Redis实例在各个大公司的应用,每个公司都需要一个Redis集群的管理工具,被迫都自己写管理工具来管理Redis集群,antirez考虑到社区的急迫需要(详情),花了几个星期写...
redis
lua-resty-redis-util:openrestylua-resty-redis封装工具类
启动redis并指定配置文件 cd /usr/local/redis ./bin/redis-server ./redis.conf #设置随机启动 vim /etc/rc.local 最后添加: /usr/local/redis/bin/redis-server /usr/local/redis/redis.conf 连接: 用redis-...