• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

Redis源码整体运行流程详解

mysql 搞代码 4年前 (2022-01-09) 65次浏览 已收录 0个评论

Redis Server端处理Client请求的流程图 main函数 main函数主要的功能为:调用initServerConfig函数,进行默认的redisServer数据结构的参数初始化;调用daemonize函数,为服务器开始守护进程,对于守护进行相关详细信息见http://blog.gaodaima.com/acceptedxukai/

Redis Server端处理Client请求的流程图

main函数

main函数主要的功能为:调用initServerConfig函数,进行默认的redisServer数据结构的参数初始化;调用daemonize函数,为服务器开始守护进程,对于守护进行相关详细信息见http://blog.gaodaima.com/acceptedxukai/article/details/8743189;调用initServer函数,初始化服务器;调用loadServerConfig函数,读取Redis的配置文件,使用配置文件中的参数替换默认的参数值;调用aeMain函数,开启事件循环,整个服务器开始工作。

initServer函数

该函数主要为初始化服务器,需要初始化的内容比较多,主要有:

1、创建事件循环

server.el = aeCreateEventLoop(server.maxclients+REDIS_EVENTLOOP_FDSET_INCR);

2、创建TCP与UDP Server,启动服务器,完成bind与listen

/* Open the TCP listening socket for the user commands. */    //server.ipfd是个int数组,启动服务器,完成bind,listen    if (listenToPort(server.port,server.ipfd,&server.ipfd_count) == REDIS_ERR)        exit(1);    /* Open the listening Unix domain socket. */    if (server.unixsocket != NULL) {        unlink(server.unixsocket); /* don't care if this fails */        server.sofd = anetUnixServer(server.neterr,server.unixsocket,server.unixsocketperm);        if (server.sofd == ANET_ERR) {            redisLog(REDIS_WARNING, "Opening socket: %s", server.neterr);            exit(1);        }    }

Redis2.8.2 TCP同时支持IPv4与IPv6,同时与之前版本的Redis不同,此版本支持多个TCP服务器,listenToPort函数主要还是调用anetTcpServer函数,完成socket()–>bind()–>listen(),下面详细查看下TCPServer的创建,UDP直接忽略吧,我也不知道UDP具体用在哪。

static int anetListen(char *err, int s, struct sockaddr *sa, socklen_t len) {    //绑定bind    if (bind(s,sa,len) == -1) {        anetSetError(err, "bind: %s", strerror(errno));        close(s);        return ANET_ERR;    }    /* Use a backlog of 512 entries. We pass 511 to the listen() call because     * the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1);     * which will thus give us a backlog of 512 entries */    //监听    if (listen(s, 511) == -1) {        anetSetError(err, "listen: %s", strerror(errno));        close(s);        return ANET_ERR;    }    return ANET_OK;}static int _anetTcpServer(char *err, int port, char *bindaddr, int af){    int s, rv;    char _port[6];  /* strlen("65535") */    struct addrinfo hints, *servinfo, *p;    snprintf(_port,6,"%d",port);    memset(&hints,0,sizeof(hints));    hints.ai_family = af;    hints.ai_socktype = SOCK_STREAM;    //套接字地址用于监听绑定    hints.ai_flags = AI_PASSIVE;    /* No effect if bindaddr != NULL */    //可以加上hints.ai_protocol = IPPROTO_TCP;    /**getaddrinfo(const char *hostname, const char *servicename,                   const struct addrinfo *hint,struct addrinfo **res);       hostname:主机名       servicename: 服务名       hint: 用于过滤的模板,仅能使用ai_family, ai_flags, ai_protocol, ai_socktype,其余字段为0       res:得到所有可用的地址    */    if ((rv = getaddrinfo(bindaddr,_port,&hints,&servinfo)) != 0) {        anetSetError(err, "%s", gai_strerror(rv));        return ANET_ERR;    }    //轮流尝试多个地址,找到一个允许连接到服务器的地址时便停止    for (p = servinfo; p != NULL; p = p->ai_next) {        if ((s = socket(p->ai_fam<em style="color:transparent">本文来源[email protected]搞@^&代*@码)网9</em>ily,p->ai_socktype,p->ai_protocol)) == -1)            continue;        if (af == AF_INET6 && anetV6Only(err,s) == ANET_ERR) goto error;        //设置套接字选项setsockopt,采用地址复用        if (anetSetReuseAddr(err,s) == ANET_ERR) goto error;        //bind, listen        if (anetListen(err,s,p->ai_addr,p->ai_addrlen) == ANET_ERR) goto error;        goto end;    }    if (p == NULL) {        anetSetError(err, "unable to bind socket");        goto error;    }error:    s = ANET_ERR;end:    freeaddrinfo(servinfo);    return s;}//if server.ipfd_count = 0, bindaddr = NULLint anetTcpServer(char *err, int port, char *bindaddr){    return _anetTcpServer(err, port, bindaddr, AF_INET);}

3、将listen的端口加入到事件监听中,进行监听,由aeCreateFileEvent函数完成,其注册的listen端口可读事件处理函数为acceptTcpHandler,这样在listen端口有新连接的时候会调用acceptTcpHandler,后者在accept这个新连接,然后就可以处理后续跟这个客户端连接相关的事件了。

/* Create an event handler for accepting new connections in TCP and Unix     * domain sockets. */     //文件事件,用于处理响应外界的操作请求,事件处理函数为acceptTcpHandler/acceptUnixHandler     //在networking.c    for (j = 0; j  0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE,        acceptUnixHandler,NULL) == AE_ERR) redisPanic("Unrecoverable error creating server.sofd file event.");

acceptTcpHandler函数


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:Redis源码整体运行流程详解
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址