自顶向下redis4.0(1)启动
redis4.0的启动流程
简介
redis 在接收客户端连接之前,大概做了以下几件事情:
- 初始化服务端配置
- 初始化服务器
- 进入事件主循环
正文
全局server对象
在redis中,有一个全局的对象server保存了redis服务器对象的信息,redis服务器的操作都围绕着该对象展开。下文中当提及server对象,默认指redis的该全局server对象。
typedef struct redisServer {
pid_t pid; /* Main process pid */
redisDb *db;
aeEventLoop *el;
// networking
int port; /* Tcp listening port */
int tcp_backlog;
int ipfd[CONFIG_BINDADDR_MAX]; /* TCP socket file descriptors */
int ipfd_count; /* Used slots in ipfd[] */
char *bindaddr[CONFIG_BINDADDR_MAX]; /* Addresses we should bind to */
int bindaddr_count; /* Number of addresses in server.bindaddr[] */
char neterr[ANET_ERR_LEN]; /* Error buffer for anet.c */
list *clients; /* List of active clients */
/* Limits */
unsigned int maxclients; /* Max number of simultaneous clients */
uint64_t next_client_id;
int dbnum; /* Total number of configured DBs */
int verbosity; /* Loglevel in redis.conf */
} redisServer;
初始化配置
redis的入口位于 server.c 的main函数,main函数中最为重要的几个函数为initServerConfig,initServer 以及aeMain函数。
int main (int argc, char *argv){
initServerConfig();
initServer();
aeMain(server.el);
}
initServerConfig函数为server对象设置了配置的默认值。这些默认值大多定义在文件server.h中。initServerConfig并不负责分配内存,需要分配内存的操作被放在initServer中执行。
void initServerConfig(void) {
server.port = CONFIG_DEFAULT_SERVER_PORT;
server.bindaddr_count = 0;
server.dbnum = CONFIG_DEFAULT_DBNUM;
server.ipfd_count = 0;
server.maxclients = CONFIG_DEFAULT_MAX_CLIENTS;
server.next_client_id = 1;
}
初始化服务器
initServer函数分配了server对象中clients链表,db数组所需的内存,设置了监听端口,将监听端口的文件描述符在多路复用API中注册。
void initServer(void) {
int j;
server.pid = getpid();
server.clients = listCreate();
// 创建server事件循环所需内存
server.el = aeCreateEventLoop(server.maxclients+128);
//监听端口, 此时只调用了 bind 和 listen函数,并将绑定的后的文件描述符传回给server.ipfd数组
if(server.port !=0 &&
listenToPort(server.port, server.ipfd, &server.ipfd_count)== C_ERR)
exit(1);
// 为db 分配内存,并为每个db创建对象的dict和过期时间的dict
server.db = zmalloc(sizeof(redisDb)*server.dbnum);
for(j = 0; j < server.dbnum; j++) {
server.db[j].dict = dictCreate(&dbDictType,NULL);
server.db[j].expires = dictCreate(&keyptrDictType,NULL);
server.db[j].id = j;
}
for (j = 0; j < server.ipfd_count; j++) {
// 对每个绑定的套接字创建文件事件,对于epoll,是将该文件描述符通过epoll_ctl进行注册
if (aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE,
acceptTcpHandler,NULL) == AE_ERR){
serverLog(LL_WARNING,
"Unrecoverable error creating server.ipfd file event.");
}
}
}
事件主循环
aeMain函数主要处理了多路复用事件的响应, 在没有接受客户端请求之前,服务器实际上一直在等待多路复用API中等待客户端连接TCP的请求。aeProcessEvents函数中调用了aeApiPoll函数,在4.0源码中,一共有4处地方定义了aeApiPoll,具体调用哪个函数,是在编译时提供的变量决定的。
#ifdef HAVE_EVPORT
#include "ae_evport.c"
#else
#ifdef HAVE_EPOLL
#include "ae_epoll.c"
#else
#ifdef HAVE_KQUEUE
#include "ae_kqueue.c"
#else
#include "ae_select.c"
#endif
#endif
#endif
我们可以看作aeApiPoll是对系统函数的一层封装。aeApiPoll函数会将触发事件的文件描述符放入server.eventLoop.fired数组中,并返回触发事件的数量。如果没有时间事件,没有设置超时,并且没有客户端请求触发事件,redis服务器将会一直阻塞。
int aeProcessEvents(aeEventLoop *eventLoop, int flags)
{
int processed = 0, numevents;
int j;
struct timeval tv, *tvp;
tvp = NULL; /* wait forever */
/* Call the multiplexing API, will return only on timeout or when
* some event fires. */
numevents = aeApiPoll(eventLoop, tvp);
for (j = 0; j < numevents; j++) {
aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];
int mask = eventLoop->fired[j].mask;
int fd = eventLoop->fired[j].fd;
int fired = 0; /* Number of events fired for current fd. */
if (!invert && fe->mask & mask & AE_READABLE) {
fe->rfileProc(eventLoop,fd,fe->clientData,mask);
fired++;
}
processed++;
}
return processed; /* return the number of processed file/time events */
}
对于还未接受客户端请求的服务器,此时接受的是TCP请求连接事件,会接着调用注册在aeFileEvent->rfileProc中的acceptTcpHandler函数。
参考文献
自顶向下redis4.0(1)启动的更多相关文章
- 自顶向下redis4.0(3)命令与dict
redis4.0的命令 简介 目录 redis4.0的命令 简介 正文 redisCommand与redisCommandTable 初始化命令 执行命令 set指令与字典 参考文献 正文 redis ...
- 自顶向下redis4.0(2)文件事件与客户端
redis4.0的文件事件与客户端 目录 redis4.0的文件事件与客户端 简介 正文 准备阶段 接受客户端连接 处理数据 返回数据结果 参考文献 简介 文件事件的流程大概如下: 在服务器初始化时生 ...
- 自顶向下redis4.0(5)持久化
redis4.0的持久化 目录 redis4.0的持久化 简介 正文 rdb持久化 save命令 bgsave命令 rdb定期保存数据 进程结束保存数据 aof持久化 数据缓冲区 刷新数据到磁盘 ap ...
- 自顶向下redis4.0(4)时间事件与expire
redis4.0的时间事件与expire 目录 redis4.0的时间事件与expire 简介 正文 时间事件注册 时间事件触发 expire命令 删除过期键值 被动删除 主动删除/定期删除 参考文献 ...
- redis4.0.13主从、哨兵、集群3种模式的 Server端搭建、启动、验证
本文使用的是redis-4.0.13.tar.gz版本. 两个centos7系统虚拟机:192.168.10.140.192.168.10.150 redis各版本下载地址:http://downlo ...
- Redis4.0.0 安装及配置 (Linux — Centos7)
本文中的两个配置文件可在这里找到 操作系统:Linux Linux发行版:Centos7 安装 下载地址,点这里Redis4.0.0.tar.gz 或者使用命令: wget http://downlo ...
- linux 安装redis4.0.6
1.进入/usr/local/src目录,下载redis # cd /usr/local/src# wget http://download.redis.io/releases/redis-4.0.6 ...
- Redis4.0 Cluster — Centos7
本文版权归博客园和作者吴双本人共同所有 转载和爬虫请注明原文地址 www.cnblogs.com/tdws 一.基础安装 wget http://download.redis.io/releases/ ...
- centos6 安装redis-4.0.9
从redis官网下载Linux redis4.0.9版本,我下载的redis-4.0.9.tar.gz(目前最新稳定版),下载到/usr/local/src目录,如果没有就mkdir创建一个. 下载链 ...
随机推荐
- [从源码学设计]蚂蚁金服SOFARegistry之程序基本架构
[从源码学设计]蚂蚁金服SOFARegistry之程序基本架构 0x00 摘要 之前我们通过三篇文章初步分析了 MetaServer 的基本架构,MetaServer 这三篇文章为我们接下来的工作做了 ...
- a标签中的target
html中target四种选择_blank._parent._self._top,分别是什么意思? eg:<Cell title="Open link in new window&qu ...
- Linux下Docker容器安装与使用
注:作者使用的环境是CentOS 7,64位,使用yum源安装. 一.Docker容器的安装 1.查看操作系统及内核版本,CentOS 7安装docker要求系统为64位.系统内核版本为 3.10及以 ...
- CLH lock queue的原理解释及Java实现
目录 背景 原理解释 Java代码实现 定义QNode 定义Lock接口 定义CLHLock 使用场景 运行代码 代码输出 代码解释 CLHLock的加锁.释放锁过程 第一个使用CLHLock的线程自 ...
- CENTOS 7平滑升级PHP到最新版7.3
安装Remi和EPEL数据源(仓库) rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm r ...
- 手把手教你使用Vue/React/Angular三大框架开发Pagination分页组件
DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师.官方网站:devui.designNg组件库:ng-devui(欢迎S ...
- 安装spyder记录
sudo apt-get install spyder 报错:ERROR: Could not find a version that satisfies the requirement pyqt5& ...
- day1(Django)
1,web项目工作流程 1.1 了解web程序工作流程 1.2 django生命周期 2,django介绍 目的:了解Django框架的作用和特点作用: 简便.快速的开发数据库驱动的网站 Djan ...
- 详解Hadoop3.x新特性功能-HDFS纠删码
文章首发于微信公众号:五分钟学大数据 EC介绍 Erasure Coding 简称EC,中文名:纠删码 EC(纠删码)是一种编码技术,在HDFS之前,这种编码技术在廉价磁盘冗余阵列(RAID)中应用 ...
- opencv-python imread、imshow浏览目录下的图片文件
☞ ░ 前往老猿Python博文目录 ░ 一.几个知识点 1.1.使用Python查找目录下的文件 具体请参考<Python正则表达式re模块和os模块实现文件搜索模式匹配>. 1.2.o ...