Redis的客户端服务端连接-事件驱动前言
事件驱动是Redis的最核心功能,
但在看这部分源码之前需要先了解Redis是怎么建立一个 C/S 连接的。
事件驱动分为两部分,
· 文件事件
· 时间事件
时间事件很好理解,就是一个定时任务,对当前Redis环境的信息统计,内存整理。
文件事件比较晦涩,特别是对于从来没接触过Unix系统,在Unix上写过代码的人来说,这部分代码可能会占到整个源码阅读时间的1/3。
所谓文件事件,在Redis中叫 FileEvent,
Unix的设计哲学是:一切皆为文件。
所有的设备,网络,磁盘,都会被Unix系统当做一个文件处理,称为 FileDescriptor。
而 client / server 的连接也是一个 FileDescriptor。
C/S连接概要
上图是Redis C/S连接的概要,分为几个部分,从做到右依次是,
· FE:file event
· FD:文件描述符,file descriptor,unix系统里的东西,详细可以单独了解unix系统的文件描述符
· Socket:网络链接。Redis的网络链接也是通过Socket来完成的。Socket链接用的是IP:port的形式,在七层网络结构里比http协议低一层。
· Client:最右边的是各个请求连接的客户端。
连接流程
一个Redis连接的建立流程,包括几个构成部分。
· Redis服务
· Redis客户端
· Unix系统,比如 Ubuntu。假设服务就运行在Ubuntu上。
连接流程是,
· 首先redis服务端启动,接着启动eventloop,也就是事件驱动。它会创建一个文件描述符FD-server。
· 然后开始监听 6397 默认端口,产生一个socket连接。socket连接建立的时候会返回一个文件描述符FD-listen。注意此时客户端还没有和服务器连接,甚至客户端都可以不存在。这个socket处于监听状态。
· 客户端请求连接,6397 端口会收到一个accept,此时生成新的一个文件描述符FD-accept。
· 服务端会绑定 FD-server 和 FD-accept
· 之后服务端就只监听 FD-server ,当发生IO的时候,可以从FD-server拿或者写数据。
对应上图,FD-server就是中间大写的FD。
从源码角度看,Fd-server,是在 createEventLoop 的时候就创建的,
在 ae.c 的createEventLoop() 中,会调用 aeApiCreate(),
根据不同的系统,会使用不同的api,
比如 ubuntu 会使用 ae_epoll.c 的 aeApiCreate(),
static int aeApiCreate(aeEventLoop *eventLoop) {
aeApiState *state = zmalloc(sizeof(aeApiState));
if (!state) return -1;
state->events = zmalloc(sizeof(struct epoll_event)*eventLoop->setsize);
if (!state->events) {
zfree(state);
return -1;
}
state->epfd = epoll_create(1024); /* 1024 is just a hint for the kernel */
if (state->epfd == -1) {
zfree(state->events);
zfree(state);
return -1;
}
eventLoop->apidata = state;
return 0;
}
state->epfd,就是上面说的FD-server文件描述符的实际对象。
整个Redis声明周期里只有一个EventLoop,也只有一个epfd。
上一篇: H5合成海报详解
下一篇: MSF以及Samba漏洞利用