VPS参考测评推荐
专注分享VPS主机优惠信息
衡天云优惠活动
热网互联2025年促销活动
hostkvm优惠促销活动
zji优惠促销活动
最新

与Redis学习事件驱动的设计

主机参考:VPS测评参考推荐/专注分享VPS服务器优惠信息!若您是商家可以在本站进行投稿,查看详情!此外我们还提供软文收录、PayPal代付、广告赞助等服务,查看详情!
我们发布的部分优惠活动文章可能存在时效性,购买时建议在本站搜索商家名称可查看相关文章充分了解该商家!若非中文页面可使用Edge浏览器同步翻译!PayPal代付/收录合作

01

为什么C程序员需要读取redis源代码

主要原因是“简洁”。 如果您使用源代码编译Redis,则是一个非常活跃的一步。 其他语言的开发人员可能不了解这种痛苦。 作为C/C ++程序员,如果您编译并安装了开源产品(例如Nginx/grpc/thrift/boost),则您有许多依赖关系,并且您的依赖性具有自己的依赖性。 通常需要半天的时间。 我真诚地想要NPM/Maven/pip/Composer/...这些包装管理人员。 雷迪斯(Redis)使人们感到惊讶,并将这一生活带入了生活。

除了简单的安装过程外,代码也非常简洁。 纯C中编写的每个模块在函数之间都有明显的区别。

让我们谈谈胡说八道。在本文中,我们将介绍Redis中的事件处理功能。 与Memcache的肿的事件库不同,它引入了Libevent,Redis本身实现了一个小型,轻巧的事件驱动的库,AE。 阅读源代码是一次很棒的学习体验。

02

清洁清洁的跨平台兼容性

文件名称描述AE.H/ae..c主文件取决于以下文件,具体取决于您的OS平台:平台

ae_kqueue.c.cqueue.c

bsd platfort </p

p> Platforms

ae_select.c

其他Unix平台

源代码文件就像ae_evport.c,ae_select.c,这四个文件中的函数完全相同,提供了一个一致的API接口并调用AE.C文件。 这是因为高性能事件驱动的API(称为投票API)没有ANSI或POSIX标准,并且不同的OS内核具有自己的实现。 例如,epoll for ux内核,kqueue for BSD内核。 ae.c包含:

代码语言:javaScriptCode运行:0运行copy #ifdef has_evport#include ae_evport.c“ ae_evport.c” #else#else#epldef has_epoll #include #include“ ae_select.c.c” ae_select.c“ ae_select.c” 为什么这是? 您可以自己考虑。

这些宏以config.h定义。 根据不同的操作系统,已经引入了这四个文件之一。 从功能上讲,我个人认为该设计的目的类似于“适配器模式”(更改为一致的接口)或“外观模式”(抽象的复杂接口是一个简单的接口)的想法,但实际上,它类似于POSA中提到的“包装器外面模式”(第2卷)。 无论如何,这个编程的想法值得学习。

03

aeeventloop:使用C ++设计,在十年前用C

编码,从C ++的Linux攻击之父开始,这是C或C ++在社区中是对的,C ++是对的。 在中国,战争始于前CSDN主编Liu Jiang的文章的一句话,战争被烧毁了该国。 孟·扬,云冯和庞巴都被困在其中。 Meng Yan的陈述“由C设计,在C ++中进行编码”为在中国的讨论中定下了基调。

相比之下,redis纯粹是c编码的,但结合了面向对象的思维。 与上面的视图相反,您可以说“使用C ++在C中进行设计和编码”。 当然,本文的目的不是引起语言冲突。各种语言都有自己的优势和缺点。开源项目的语言选择主要是由于项目作者的个人经验和主观愿望。

AE.H aeeventloop中定义的结构是AE库的核心数据结构,采用面向对象的设计思想。 AE.H声明多个函数,第一个参数是AEEVENTLOOP指针。 从这个角度来看,结构可以理解为以对象为导向的语言中的类,而操纵它们的功能可以视为成员函数。 (实际上,C ++类可能类似于后编译

function

说明

awcreateeeventloop

eventloop struction(eventloop)

aegetSetsize

aegetSetsize

aegetSize

aegetSetsize

SetSize (Reallocate Space)

aedeteeventeventloop

Delete event loop and remove memory space for free

Stop event loop, i.enotstop value is 1

aecore

aecore:aecore:aecore:p>aecore:p> aecore:p> logic

aeMain

Start the event loop, the entry of the event loop

aeSetBeforeSleepProc

Register the callback function, and each main loop is called before sleep

aeCreateEventLoop and aeDeleteEventLoop can be considered as the "class" aeeventloop's constructor and destroyer,其他是成员函数。

当您调用程序中的AE库时,通常会按顺序调用:

createeventlOOP注册文件事件或时间事件Aesetbeforesleocaemainaedeteeteeventloop

3-1

ae两个事件

事件处理与多阅读/多程序同时模型不同。 我也知道Redis是单线线程。 该性能主要是通过异步事件处理功能来实现的。 事件处理通常与网络编程相混淆,但是事件处理本身不一定对网络编程有用。它主要帮助IO。网络通信是IO,并且阅读和编写文件是相同的。 当然,Unix中的所有内容都是一个文件,插座也是一种FD。

AE支持两种类型的事件。

文件事件(IO)时间事件(毫秒级)

两个事件都作为AEEVENTLOOP的结构成员存在。 aeeventloopmember描述:

代码语言:javascriptCode运行时间:0运行复制 typedef struct aeeventloop {int maxfd; / *当前注册的最大fd */ int Setsize; / *最大要监视的FDS数量 */ long Pime EventNextID; / *下一个事件的ID */ time_t lastime; / *上次事件处理时间 */ aefileevent *事件。 / *注册的文件事件阵列 */ aefiredevent *fileed; / *就绪文件事件阵列 */ aetemenevent *timeventhead; / *时间事件列表的标题 */ int stOP; /*是否停止(0:否; 1:是)*/ void*apida; / *投票为每个平台的API */ aebeforesleepproc *beforeslep的特定数据; / *在事件循环睡眠开始时自定义功能 */睡眠后的aebeforesleepproc *。 / *事件结束时处理功能循环睡眠 */} aeeventloop;

文件事件主要依赖于两个数组。 一个是注册的文件事件阵列,另一个是“就绪文件事件”数组。

代码语言:javascript代码运行时:0运行复制 typedef struct aefiledevent {int mask; / *一个 *ae_(可读|可写的|屏障) */ aefileproc *rfileproc; aefileproc *wfileproc; void *clientdata;} aefileevent; 代码语言:javascript代码运行时:0运行复制 typedef struct aefiredevent {int fd; int mask;} aefiredEvent;

填充的单词具有通知的含义。在这里,您可以将其理解为“准备就绪”

每个文件事件。 此外,掩码代表触发类型事件。 当每个投票API返回准备就绪时(EPOLL_WAI等)t返回),即将设置为aefireevent,它可以反向检查AefileEvent以获取处理程序功能并处理它。 您可以看到FD未记录在AefileEvent结构中。 实际上,这使用了哈希策略。 AEFILEEVENT ARRAY ARRAY ARRAY订阅是FDS,使其可用于快速搜索。

时间事件本质上是计时器任务,其数据结构使用双向链接列表。 链接列表中的每个节点主要是包含事件ID(增量),现成的时间,处理功能,清洁功能和客户数据的AtemeneEvent结构。

代码语言:javascript代码运行时:0运行复制 typedef struct a eTimentevent {long long ID; /*时间事件标识符。 */ long_sec; / *秒 */ long_ms; / *数百万秒 */ aetimeProc *TimeProc; aeeventFinalizerProc *finalizerProc; void *clientdata; struct aetemenevent *prev; struct a eTimeEvent *next;} aetemenevent;

在每个事件循环中,每个时事件的ID都唯一地增加,并且主要依赖AEEVentloop的TimeVentNextID来维护此ID增量关系。 创建新的时间事件(AECREATETEMETEVENT)时会分配它。没有锁定逻辑,因为仅考虑一个线程。不要急于在多线程环境中使用AE。

_sec和_ms记录时间事件(秒 +毫秒),即当前的时间(秒 +毫秒)。如果时间比这个时间更长,则必须处理时间事件。

时间事件的过程主要如下:如果它继续通过链接列表并发现节点状态为ae_deleted_event_id,请删除节点。 如果确定当前时间超过了节点的现成时间,则将开始处理。 您可以指定处理功能的返回值。如果事件不再处理(nomore),则将节点设置为ae_deleted_event_id。 如果仍然需要下一个进程,那么更新节点的时间是下次。

3-2

事件循环处理逻辑

如果您使用另一张照片查看Eventloop中的两个事件,则基本上可以理解以下内容:链接列表,数组。 文件事件的数组没有线性填充,因为它是使用的哈希策略。 FD用作数组下标。

aeprocessevents是循环中Aeeventloop的实际处理逻辑。 功能原型为:

代码语言:JavaScript代码执行:0运行并复制 int aeprocessevents(aeeventloop *eventloop,int flag);

标志标签。

markbit

含义

ae_time_events

时间事件tag

ae_file_events

文件事件tag

ae_dont_wait

ae_dont_wait

请不要发布。 聪明的地方是一次减轻文件和时间事件的两个处理过程。 在功能开始时,发现了一个链接的时间事件列表,发现了最新的准备时间事件,并且当前时间已经准备就绪。差异用作轮询API的睡眠时间(EPOLL_WAIT超时参数)。 之后,我去睡觉,等待API返回。 返回后,首先执行了毕业后处理逻辑,然后在此睡眠期间执行就绪文件事件,最终处理了准备时间事件。 返回值是处理的事件总数。

换句话说,AES将在一个处理过程中处理时间事件,并尝试一次提交事件。 如果没有时间事件,您可以问该怎么办。 当然,这不是问题。 Aeprocessevents从标记位开始。 上面的逻辑取决于是否存在文件事件和时间事件,如果仅存在文件事件,则是否设置了非阻滞标记(AE_DONT_WAIT)。在这种情况下,民意调查超时时间设置为0。块无需设置,然后设置为-1,然后将轮询API阻止,直到发生文件事件为止。

04

ae_epoll:Linux中的Epoll封装

上一篇文章指出,Redis适用于各种类似Unix的操作系统。 提取事件API(轮询API)的部分与内核很密切相关,并将相同接口包裹在AE的外部API调用中。 Linux系统的API实现是AE_EPOLL.C。建议您在阅读此文件的源代码之前检查Epoll API。这将帮助您快速理解它。 下班后,每个人都撰写了商业逻辑,并认为他们很少接触过Epoll。 阅读此WIK以快速检查Epoll的API。 linuxapi:epoll

ae_epoll.c完全由AE.C调用。 函数调用的关系如下(AEAPI从ae_epoll.c中的一个函数开始):ae.c

deletefileeepideepideepideeprocesseventaepolleaegetapideapideepideepideepideepideepideepideepideepideeepina

除了aeapiname()之外,其他函数的第一个参数也是AEEVENTLOOP *。 从面向对象的想法中,这也是AEEVentloop的成员函数。 如果是C ++,请想象AEAPI系列中的功能纯粹是虚拟的,同时仍可能由两个类来处理。 AEAPI函数也可以是其名称所建议的。 例如,

aeapicreate将内存分配给堆,封装epoll_create创建EPFD,并写下Aeeventloop。 Aeapiaddevent和Aeapidelevent是封装的EPOLL_CTL,用于添加和删除由AEEVENTLOOP监视的EPOLL事件。 Aeapipoll是一个封装的EPOLL_WAIT,可打开事件循环,并将Ready FD获取并保存到Aeeeventloop射击阵列中,设置相应的面膜(读取或写入),并设置Aeapifree Aeapree aeapree aeapree aeapree aeapree aeapree aeapree forment formention Redistibution,资源清洁,闭幕EPFD,EPFD,EPFD,EPFD,Eply and Epoll本身。

05

实际上,它没有什么太浮华的,但是它是如此简洁明了,以至于它提供了一个事件驱动的处理库。 但是,即使每个人都熟悉Epoll,Kqueue和数据结构,也不一定意味着他们设计AES,因此我认为将程序员与代码设计师和建筑师进行比较并不是夸张的。

AE设计的灵感实际上受到另一个开源项目Jim的影响。

显示了Redis的AE.C开放评论:

代码语言:JavaScript代码执行:0运行副本简单事件驱动的编程库。最初,我在健身事件循环(健身房是TCL Interplater)中写了此代码,但后来将其翻译成图书馆的形式,并轻松地将其重复使用。

Redis的作者说,他首先为JIM项目创建了一个代码集,然后将其转换为简单的重复使用库。

实际上可以没有重新介绍。 这种松散的连接是设计的吸引力。

健身源代码在GitHub上具有一个图像,其中事件循环代码在此处:

https://github.com/msteveb/jimtcl/jimtcl/blob/master/master/jim-eventloop.c

快速读取JIM代码。 但是,AE具有创新性,例如将轮询API层提取以提供多平台的兼容性和解耦。

我们经常说“站在巨人的肩膀上”。吉姆不是巨人,但作者通过为他编写代码来启发AE。即使吉姆最终被世界遗忘了,它的血肉和血液变成了土壤,以滋养后来的几代。这是开源运动和吸引力的重要性。 学习的本质实际上是模仿和改进。这不是窃,而是继承。

驱动程序精灵

驱动程序小精灵基于驱动程序之家十年来的专业数据积累和高度驱动程序支持已解决了数亿用户的各种计算机驱动程序问题和系统故障。当前有效的驱动程序软件。有需要的朋友,来保存,下载并尝试一下!

下载

这几篇文章你可能也喜欢:

本文由主机参考刊发,转载请注明:与Redis学习事件驱动的设计 https://zhujicankao.com/148583.html

【腾讯云】领8888元采购礼包,抢爆款云服务器 每月 9元起,个人开发者加享折上折!
打赏
转载请注明原文链接:主机参考 » 与Redis学习事件驱动的设计
主机参考仅做资料收集,不对商家任何信息及交易做信用担保,购买前请注意风险,有交易纠纷请自行解决!请查阅:特别声明

评论 抢沙发

评论前必须登录!