>  기사  >  데이터 베이스  >  Redis의 epoll 및 파일 이벤트에 대해 설명하는 기사

Redis의 epoll 및 파일 이벤트에 대해 설명하는 기사

青灯夜游
青灯夜游앞으로
2021-11-03 10:55:141796검색

이 글은 Redis의 파일 이벤트에 대해 소개할 예정입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

Redis의 epoll 및 파일 이벤트에 대해 설명하는 기사

Event-driven

Redis 서버는 파일 이벤트시간 이벤트文件事件时间事件

  • 文件事件:socket 的可读可写事件
  • 定时任务

【相关推荐:Redis视频教程

它们都被封装到aeEventLoop结构体中

typedef struct aeEventLoop {
	int stop; // 标识事件是否结束
	aeFileEvent *events; // 文件事件数组,存储已注册的文件事件
	aeFireEvent *fired; // 存储被触发的文件事件
	aeTimeEvent *timteEventHead; // 多个时间事件形成的链表
	void *apidata; // I/O模型的封装
	aeBeforeSleepProc *beforesleep; // 进程阻塞前执行
	aeBeforeSleepProc *aftersleep; // 进程被唤醒后执行
} aeEventLoop;

事件驱动程序实际上也是通过while/for循环,循环等待事件的发生

while (! eventLoop->stop) {
	if (eventLoop->beforesleep != NULL)
		eventLoop->beforesleep(eventLoop)
	aeProcessEvents(eventLoop, AE_ALL_EVENTS|AE_CALL_AFTER_SLEEP);
}

aeProcessEvents为事件处理主函数

epoll

Redis 客户端通过 TCP socket 与服务端交互,文件事件指的就是 socket 的可读可写事件。一般使用非阻塞模式,相关的 I/O 多路复用有select/epoll/kqueue等,不同的操作系统不同的实现。

epoll为例,它是 Linux 内核为处理大量并发网络连接而提出解决方案。epoll提供3个 API

  • epoll_create 创建一个 epoll 专用的文件描述符,用于后续 epoll 相关 API 调用

int epoll_create(int size)
// size 告知内核程序期望注册的网络连接数目,Linux 2.6.8后改为内核动态分配
// 返回参数是 epoll 专用的文件描述符
  • epoll_ctl 函数向 epoll 注册、修改或删除需要监控的事件

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
// epfd 函数 epoll_create 返回的 epoll 文件描述符
// op 操作类型 EPOLL_CTL_ADD:注册事件; EPOLL_CTL_MOD:修改网络连接事件; EPOLL_CTL_DEL:删除事件
// fd 网络连接的 socket 文件描述符
// event 需要监控的事件
  • epoll_wait 函数会会阻塞进程,直到监控的若干网络连接有事件发生

int epoll_wait(int epfd, struct epoll_event *event, int maxevents, int timeout)
// epfd 函数epoll_create返回的epoll文件描述符
// epoll_event 作为输出参数使用,用于回传已触发的事件数组
// maxevents 每次能处理的最大事件数目
// timeout epoll_wait 函数阻塞超时时间,如果超过 timeout 时间还没有事件发生,函数就不再阻塞直接返回;当 timeout 等于0是函数立即返回,timeout 等于-1时函数一直阻塞到有事件发生

文件事件

Reids 没有直接使用 epoll 的 API,而是同时支持4种I/O多路复用模型,对这些模型的 API 进行了封装。然后在编译阶段检查操作系统支持的I/O多路复用模型,并按照策略来决定复用那张模型。

还是以 epoll 为例,Redis 进行了如下封装

// 对应 epoll_create
static int aeApiCreate(aeEventLoop *eventLoop)

// 对应 epoll_ctl 添加事件
static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask)
// 对应 epoll_ctl 删除事件
static int aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask)

// 对应 epoll_wait
static int aeApiPool(aeEventLoop *eventLoop, struct timeval *tvp)

回忆一下上面提到的eventLoop结构体,其成员 apidata 指向4种I/O多路复用模型对象;events 存储需要监控的事件数组,以 socket 文件描述符作为数组索引存取元素;fired 存储已触发的事件数组。

文件事件的结构体定义如下:

typedef struct aeFileEvent {
	int mask; // 文件事件类型 AE_READABLE 可读事件;AE_WRITEABLE 可写事件
	aeFileProc *rfileProc; // 读事件处理函数指针
	aeFileProc *wfileProc; // 写事件处理函数指针
	void *clientData; // 指向对应的客户端对象
} aeFileEvent;

看一下创建文件事件 aeCreateFileEvent 的实现

int aeCreateFileEvent (aeEventLoop *eventLoop, int fd, int mask, aeFileProc *proc, void *clientData) {
	aeFileEvent *fe = &eventLoop->evnts[fd];
	if (aeApiAddEvent(eventLoop, fd, mask) == -1)
		return AE_ERR;
	fe->mask |= mask;
	if (mask & AE_READABLE) fe->rfileProc = proc;
	if (mask & AE_WRITABLE) fe->wfileProc = proc;
	fe->clientData = clientData;
	return AE_OK;
}

Redis 服务器会通过创建各类文件事件来处理事务,比如:

  • 启动时创建 socket 并监听,等待客户端连接
aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE, acceptTcpHandler, NULL);
  • 客户端与服务器建立 socket 连接之后,服务器会等待客户端的命令请求
aeCreateFileEvent(server.el, fd, AE_READABLLE, readQueryFromClient, c);
  • 服务器处理完客户端的命令请求之后,命令回复会暂时缓存在client结构体的buf缓冲区,待客户端文件描述符的可写事件发生时,才会真正往客户端发送命令回复
aeCreateFileEvent(server.el, c->fd, AE_READABLLE, sendReplyToClient, c);

Redis 所有事件的执行都是通过aeProcessEvents

파일 이벤트로 구분되는 이벤트 중심 프로그램입니다. 소켓에서 읽을 수 있습니다. 및 이벤트 작성 예약된 작업

[관련 권장 사항: Redis 비디오 튜토리얼】

모두 aeEventLoop 구조로 캡슐화되어 있습니다Redis의 epoll 및 파일 이벤트에 대해 설명하는 기사

int aeProcessEvents(aeEventLoop *eventLoop, int flags) {
	shortest = aeSearchNearestTimer(eventLoop);
	long long ms = (shortest->when_sec - now_sec) * 1000 + \
		shortest->when_ms - now_ms;

	// 阻塞事件发生
	numevents = aeApiPoll(eventLoop, ms);

	for (j=0; j < numevents; j++) {
		aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j]].fd];
		// 处理文件事件,即根据类型执行rfileProc或wfileProc
	}

	// 处理时间事件
	processed += processTimeEvents(eventLoop);
}

이벤트 드라이버는 실제로 while/for 루프를 통해 이벤트가 발생할 때까지 기다립니다

rrreee

aeProcessEvents는 주요 이벤트 처리 기능입니다

    epoll
  • Redis 클라이언트는 TCP 소켓을 통해 서버와 상호 작용합니다. 파일 이벤트는 소켓의 읽기 및 쓰기 가능한 이벤트를 참조합니다. 일반적으로 비차단 모드가 사용됩니다. 관련 I/O 다중화에는 select/epoll/kqueue 등이 포함됩니다. 운영 체제마다 구현이 다릅니다.
  • epoll을 예로 들어보겠습니다. 이는 많은 수의 동시 네트워크 연결을 처리하기 위해 Linux 커널에서 제안한 솔루션입니다. epoll은 3개의 API를 제공합니다

    • epoll_create는 후속 epoll 관련 API 호출을 위한 epoll 관련 파일 설명자를 생성합니다
    • rrreee

        🎜epoll_ctl 함수는 epoll🎜🎜
      rrreee
        🎜🎜epoll_wait 함수는 모니터링되는 여러 네트워크 연결에서 이벤트가 발생할 때까지 프로세스를 차단합니다🎜🎜
      rrreee🎜🎜File events🎜🎜🎜Reids는 epoll API를 직접 사용하지 않지만 동시에 지원합니다. time 4 I/O 멀티플렉싱 모델은 이러한 모델의 API를 캡슐화합니다. 그런 다음 컴파일 단계에서 운영 체제에서 지원하는 I/O 다중화 모델을 확인하고 전략에 따라 어떤 모델을 재사용할지 결정합니다. 🎜🎜또한 epoll을 예로 들면 Redis는 다음과 같이 캡슐화됩니다. 🎜rrreee🎜위에 언급된 eventLoop 구조를 떠올려 보세요. 해당 멤버 apidata는 4가지 유형의 I/O 다중화 모델 개체를 가리킵니다. 이벤트를 저장합니다. 모니터링해야 하는 배열, 실행된 요소에 액세스하기 위한 배열 인덱스로 소켓 파일 설명자를 사용하여 트리거된 이벤트 배열을 저장합니다. 🎜🎜파일 이벤트의 구조는 다음과 같이 정의됩니다. 🎜rrreee🎜파일 생성 이벤트 aeCreateFileEvent🎜rrreee🎜Redis 서버는 다음과 같은 다양한 파일 이벤트를 생성하여 트랜잭션을 처리합니다. 🎜🎜🎜소켓 생성 시작 및 수신 대기 클라이언트 연결🎜
    rrreee🎜🎜클라이언트가 서버와 소켓 연결을 설정한 후 서버는 클라이언트의 명령 요청을 기다립니다🎜rrreee🎜🎜서버가 클라이언트의 명령 요청을 처리한 후 명령 요청에 대한 명령 응답은 일시적으로 캐시됩니다. 클라이언트 구조의 buf 버퍼는 클라이언트 파일 설명자의 쓰기 가능한 이벤트가 발생할 때까지 클라이언트에 실제로 명령 응답을 보내지 않습니다.🎜rrreee🎜Redis 모든 이벤트가 실행됩니다. aeProcessEvents 함수를 통해 제어합니다. 그 중 파일 이벤트의 실행은 블로킹(epoll_wait)을 발생시키게 되는데, 블로킹 이벤트가 너무 길면 타임 이벤트의 실행을 방해하게 된다(timing). 이를 방지하기 위해 파일 이벤트 구현 시 대기 시간을 전달한다. 가장 빠른 시간 이벤트를 계산하여 구합니다 🎜rrreee🎜🎜Summary🎜🎜🎜이제 Redis 서버의 해당 명령의 프로세스를 전체적으로 살펴보겠습니다.🎜🎜🎜🎜🎜aeMain 함수는 aeProcessEvents 함수 구현. 이벤트 관련 정보는 aeEventLoop에 기록됩니다. 먼저 aeSearchNearestTimer 함수를 통해 가장 짧은 시간 이벤트의 실행 시간 간격 n을 얻은 후 aeApiPoll 함수를 호출하여 모니터링되는 소켓을 얻은 다음 마지막으로 소켓에 해당하는 이벤트 처리 함수 rfileProc, wfileProc를 실행하고 마지막으로 시간 이벤트를 실행합니다. 함수 processTimeEvents . 🎜🎜완전한 클라이언트-서버 연결 이벤트: 🎜🎜🎜🎜서버는 클라이언트가 연결 요청을 보내면 AE_READABLE 이벤트를 수신합니다. 서버는 클라이언트의 연결 요청에 응답하고 설정합니다. 클라이언트 인터페이스의 AE_READABLE 이벤트 및 명령 요청 처리 기능(aeFileProc), 클라이언트는 서버에 명령 요청을 보낼 수 있습니다. 🎜🎜🎜🎜클라이언트는 서버에 명령 요청을 보내고, 클라이언트 소켓은 명령을 트리거하는 AE_READABLE 이벤트를 생성합니다. 처리 서버가 이를 실행하고 명령을 실행하면 해당 명령 응답이 생성됩니다. 서버는 클라이언트 소켓의 AE_WRITABLE 이벤트를 명령 응답 처리 기능(aeFileProc)과 연결합니다. AE_WRITABLE 이벤트가 생성되어 명령 응답 프로세서의 실행이 시작됩니다. 명령 응답 프로세서가 모든 명령 응답을 소켓에 기록하면 서버는 클라이언트 소켓의 AE_WRITABLE 이벤트와 명령 응답 처리 기능 간의 연결에 연결됩니다. (aeFileProc).<p>더 많은 프로그래밍 관련 지식을 보려면 <a href="https://www.php.cn/course.html" target="_blank" textvalue="编程视频">프로그래밍 비디오</a>를 방문하세요! ! </p>

    위 내용은 Redis의 epoll 및 파일 이벤트에 대해 설명하는 기사의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제