返回顶部
首页 > 资讯 > 数据库 >怎么理解Redis中的epoll和文件事件
  • 936
分享到

怎么理解Redis中的epoll和文件事件

2024-04-02 19:04:59 936人浏览 八月长安
摘要

这篇文章主要讲解了“怎么理解Redis中的epoll和文件事件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Redis中的epoll和文件事件”吧!

这篇文章主要讲解了“怎么理解Redis中的epoll和文件事件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Redis中的epoll和文件事件”吧!

怎么理解Redis中的epoll和文件事件

事件驱动

Redis 服务器是事件驱动程序,分为文件事件时间事件

  • 文件事件:Socket 的可读可写事件

  • 定时任务

它们都被封装到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函数来控制。在其中,执行文件事件会出现阻塞情况(epoll_wait),如果阻塞事件太长了,会妨碍到时间事件(定时)的执行,为避免出现这种情况,在实现文件事件时传入的等待时间,是计算最早发生的时间事件得到的

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);
}

总结

现在我们来整体看一下 Redis 服务器相应命令的流程

怎么理解Redis中的epoll和文件事件

aeMain 函数通过调用 aeProcessEvents 函数来进行文件事件和时间事件的调度和执行。aeEventLoop 中记录了事件相关的信息。首先通过 aeSearchNearestTimer 函数获取最短的时间事件的执行时间间隔n,然后调用 aeApiPoll 函数获取监听到的套接字,最后执行与套接字向对应的事件处理函数 rfileProc 和 wfileProc,最后再执行时间事件函数 processTimeEvents。

一次完整的客户端与服务端连接事件:

  • 器监听套件字的 AE_READABLE 事件,当客户端发送连接请求产生 AE_READABLE  事件,服务端会对客户端的连接请求进行应答,将客户端套接字的 AE_READABLE 事件与命令请求处理函数(aeFileProc),客户端可以向服务端发送命令请求了

  • 端向服务端发送一个命令请求,客户端套接字将产生 AE_READABLE 事件,引发命令处理器去执行,执行命令将产生相应的命令回复,服务端将客户端套接字的 AE_WRITABLE 事件与命令回复处理函数(aeFileProc)关联

  • 端尝试读取命令回复时,客户端套接字将产生 AE_WRITABLE 事件,触发命令回复处理器执行,当命令回复处理器将命令回复全部写入套接字之后,服务器就会接触客户端套接字的 AE_WRITABLE 事件与命令回复处理函数(aeFileProc)之间的关联

感谢各位的阅读,以上就是“怎么理解Redis中的epoll和文件事件”的内容了,经过本文的学习后,相信大家对怎么理解Redis中的epoll和文件事件这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

您可能感兴趣的文档:

--结束END--

本文标题: 怎么理解Redis中的epoll和文件事件

本文链接: https://lsjlt.com/news/62840.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 怎么理解Redis中的epoll和文件事件
    这篇文章主要讲解了“怎么理解Redis中的epoll和文件事件”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解Redis中的epoll和文件事件”吧!...
    99+
    2024-04-02
  • redis文件事件和时间事件是什么
    今天小编给大家分享一下redis文件事件和时间事件是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来...
    99+
    2024-04-02
  • 如何理解Vue中的事件处理和事件修饰符
    这篇文章将为大家详细讲解有关如何理解Vue中的事件处理和事件修饰符,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。 <div id="root"&...
    99+
    2023-06-25
  • C#委托和事件怎么理解
    这篇文章主要介绍“C#委托和事件怎么理解”,在日常操作中,相信很多人在C#委托和事件怎么理解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#委托和事件怎么理解”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-17
  • onmouseover事件和onmouseout事件全面理解
    onmouseover事件是指鼠标移动到指定元素上时触发的事件,而onmouseout事件是指鼠标移出指定元素时触发的事件。onmo...
    99+
    2023-08-16
    onmouseover
  • 怎么处理WinForm中的控件事件
    在WinForm中处理控件事件通常需要以下步骤: 打开窗体设计器,选择要处理事件的控件,例如按钮、文本框等。 双击控件,会自动创建...
    99+
    2024-04-08
    winform
  • Linux系统中的/etc/passwd文件和etc/shadow文件该怎么理解
    这篇文章将为大家详细讲解有关Linux系统中的/etc/passwd文件和etc/shadow文件该怎么理解,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在Linux系统中 /etc/pas...
    99+
    2023-06-28
  • 怎么理解MySQL的EVENT事件
    这篇文章主要介绍“怎么理解MySQL的EVENT事件”,在日常操作中,相信很多人在怎么理解MySQL的EVENT事件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解My...
    99+
    2024-04-02
  • JavaScript事件该怎么理解
    JavaScript事件该怎么理解,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。JavaScript事件     HTM...
    99+
    2024-04-02
  • Django中怎么管理静态文件和媒体文件
    在Django中,可以通过设置STATIC_URL和STATICFILES_DIRS来管理静态文件,通过设置MEDIA_URL和ME...
    99+
    2024-04-02
  • Javascript 中怎么实现事件流和事件委托
    今天就跟大家聊聊有关Javascript 中怎么实现事件流和事件委托,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。javascript 事件流和事件...
    99+
    2024-04-02
  • redis文件怎么保存的
    redis文件是把数据保存到内存中的,也会定期把数据写入硬盘中。它有两种关于储存的持久化机制:RDB和AOF。RDB指的是用数据集快照的方式半持久化模式记录 redis数据库的所有键值对,在某个时间点将数据写入一个临时文件,持久化结束后,用...
    99+
    2024-04-02
  • Vue之事件处理和事件修饰符详解
    <div id="root"> <h2>{{name}},加油!</h2> <!-- 阻止默认事...
    99+
    2024-04-02
  • JavaScript中怎么捕捉事件和阻止冒泡事件
    JavaScript中怎么捕捉事件和阻止冒泡事件,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一、要探究捕获和冒泡事件,首先要...
    99+
    2024-04-02
  • 怎么理解ORACLE事件跟踪
    这期内容当中小编将会给大家带来有关怎么理解ORACLE事件跟踪,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。ORACLE事件跟踪  Oracle跟踪文件分为三种...
    99+
    2024-04-02
  • 怎么理解JavaScript事件加载
    这篇文章主要介绍“怎么理解JavaScript事件加载”,在日常操作中,相信很多人在怎么理解JavaScript事件加载问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解...
    99+
    2024-04-02
  • 怎么理解js事件委托
    这篇文章主要讲解了“怎么理解js事件委托”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么理解js事件委托”吧!每个函数都是对象,占用内存。内存中的对象越多,性能越差。解决事件处理过多问题的...
    99+
    2023-06-25
  • 怎么理解Java事件响应
    这篇文章主要介绍“怎么理解Java事件响应”,在日常操作中,相信很多人在怎么理解Java事件响应问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么理解Java事件响应”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-02
  • JavaScript事件流:深入理解事件处理和传播机制
    引言 JavaScript中的事件流是一种机制,用于描述和处理事件在DOM树中的传播过程。了解事件流的属性和工作原理对于编写高效的事件处理代码和实现复杂的交互功能至关重要。本文将详细介绍JavaSc...
    99+
    2023-09-14
    javascript 开发语言 ecmascript 原力计划
  • java中事件图文详解
    学习java事件之前,对java内部类、java常用组件、容器、布局管理器、java抽象窗口工具包这些东西有一定的了解,结合下面的知识点,可以做一些简单的窗口程序。(推荐:java视频教程)Java语言对事件的处理采用的是授权事件模型。在这...
    99+
    2021-10-07
    java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作