前言 Redis(REmoteDIctionaryServer)是一个由Salvatore Sanfilippo写的key-value存储系统。 它有以下特点: 总体结构 Redis是一个单线程的服务器(除了写磁盘会开子进程,VM管理会开线程,先忽略这两块) 所以,它的服务器启动流程非常清晰,看下图,不再
前言
redis(remote dictionary server)是一个由salvatore sanfilippo写的key-value存储系统。
它有以下特点:
总体结构
Redis是一个单线程的服务器(除了写磁盘会开子进程,VM管理会开线程,先忽略这两块)
所以,它的服务器启动流程非常清晰,看下图,不再赘述

事件循环1. 数据结构
通过 aeEventLoop 结构来表示一个事件框架,美国服务器,分析如下:
1 typedef struct aeEventLoop {timeEventNextId; aeFileEvent events[AE_SETSIZE]; aeFiredEvent fired[AE_SETSIZE]; aeTimeEvent *timeEventHead; stop;aeBeforeSleepProc *beforesleep;10 } aeEventLoop;
2. 事件函数分发流程
redis支持 epoll、kqueue、select 三种网络模型
网络框架的代码实现主要在以下几个文件中:
ae.c / ae.h // 网络框架
ae_epoll.c // epoll模型的实现
ae_kqueue.c // kqueue模型的实现
ae_select.c // select模型的实现
程序选择哪一种,网站空间,是在编译期确定的
1 1 file ae.c #ifdef HAVE_EPOLL#ifdef HAVE_KQUEUE#include
框架函数非常简单,从初始化到结束,主要的函数就3个
aeCreateEventLoop、aeMain、aeDeleteEventLoop
其中,aeMain是事件循环的主体函数,它又会调用 aeProcessEvents函数
三个主体函数会调用 aeApiCreate、aeApiPool、aeApiFree三个接口函数进行处理
这三个接口函数又会映射到具体的某一种网络模型中,而这是在编译期确定下来的
具体如下图所示:
代码小浣熊
代码小浣熊是基于商汤大语言模型的软件智能研发助手,覆盖软件需求分析、架构设计、代码编写、软件测试等环节
51 查看详情

添加删除事件,由
aeCreateFileEvent、aeDeleteFileEvent函数完成,其函数分发流程如下图:

2. 服务端socket建立流程
1. 在服务器初始化时,建立侦听socket,并绑定IP、Port
支持 TCP连接 与本机的unixSocket连接
1if (server.port != 0) {2server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr);3 … … 4 }5if (server.unixsocket != NULL) {server.sofd = anetUnixServer(server.neterr,server.unixsocket,server.unixsocketperm);8 … …9}
2. 侦听socket绑定到事件句柄
1if (server.ipfd > 0 && aeCreateFileEvent(server.el,server.ipfd,AE_READABLE,);3if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE,);
其中“acceptTcpHandler”、“acceptUnixHandler” 是事件回调函数
当新连接到达时,会触发进入这两个函数
3. 再来看看 accept***Handler 里做了什么
1 void acceptTcpHandler(aeEventLoop *el, int fd, void *privdata, int mask) { 2int cport, cfd; 3char cip[128]; 4 REDIS_NOTUSED(el); 5 REDIS_NOTUSED(mask); 6 REDIS_NOTUSED(privdata);cfd = anetTcpAccept(server.neterr, fd, cip, &cport);10if (cfd == AE_ERR) {, server.neterr);12return;13 }, cip, cport);}
acceptCommonHandler中做的事很简单,调用 CreateClient函数,创建新的redisClient对象
acceptCommonHandler(int fd) {2redisClient *c;3if ((c = createClient(fd)) == NULL) {);;7 }8 … …9 }
在 createClient函数中,将新连接绑定到事件循环中
1 redisClient *createClient(int fd) { 2redisClient *c = zmalloc(sizeof(redisClient)); 3c->bufpos = 0; 4 5 anetNonBlock(NULL,fd); 6 anetTcpNoDelay(NULL,fd); 7if (aeCreateFileEvent(server.el,fd,AE_READABLE, {10 close(fd);11 zfree(c);12return NULL;13}
当连接上有数据到达时,便会触发 readQueryFromClient函数,进行实际的网络数据读取与处理
3. Timer事件
Redis将所有Timer绑定到事件循环中进行处理
通过函数 aeCreateTimeEvent 创建新的Timer事件
每一帧事件循环中,通过processTimeEvents函数进行处理
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/471504.html
微信扫一扫
支付宝扫一扫