Maison > base de données > Redis > Un article pour parler d'epoll et des événements de fichiers dans Redis

Un article pour parler d'epoll et des événements de fichiers dans Redis

青灯夜游
Libérer: 2021-11-03 10:55:14
avant
1917 Les gens l'ont consulté

Cet article vous présentera les événements de fichiers dans Redis. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.

Un article pour parler d'epoll et des événements de fichiers dans Redis

Event-driven

Le serveur Redis est un programme piloté par des événements, divisé en Événements de fichier et Événements de temps文件事件时间事件

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

【相关推荐:Redis视频教程

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

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

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

while (! eventLoop->stop) {
	if (eventLoop->beforesleep != NULL)
		eventLoop->beforesleep(eventLoop)
	aeProcessEvents(eventLoop, AE_ALL_EVENTS|AE_CALL_AFTER_SLEEP);
}
Copier après la connexion

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 专用的文件描述符
Copier après la connexion
  • 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 需要监控的事件
Copier après la connexion
  • 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时函数一直阻塞到有事件发生
Copier après la connexion

文件事件

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)
Copier après la connexion

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

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

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

看一下创建文件事件 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;
}
Copier après la connexion

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

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

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

Événements de fichier : lisibles par socket et Écrire des événements Tâches planifiées

[Recommandations associées : Tutoriel vidéo Redis< / a>】

Ils sont tous encapsulés dans la structure aeEventLoopUn article pour parler depoll et des événements de fichiers dans Redis

Le pilote d'événement attend en fait que l'événement se produise via la boucle while/for

rrreee

aeProcessEvents est la principale fonction de traitement des événements

    epoll
  • Le client Redis interagit avec le serveur via le socket TCP. Les événements de fichier font référence aux événements lisibles et inscriptibles du socket. Généralement, le mode non bloquant est utilisé. Le multiplexage d'E/S associé inclut select/epoll/kqueue, etc. Différents systèmes d'exploitation ont des implémentations différentes.
  • Prenons epoll comme exemple. C'est une solution proposée par le noyau Linux pour gérer un grand nombre de connexions réseau simultanées. epoll fournit 3 API

    • epoll_create crée un descripteur de fichier spécifique à epoll pour les appels d'API ultérieurs liés à epoll
    • rrreee

        🎜La fonction epoll_ctl enregistre, modifie ou supprime les événements qui doivent être surveillés avec epoll🎜🎜
      rrreee
        🎜🎜La fonction epoll_wait bloquera le processus jusqu'à ce que des événements se produisent sur plusieurs connexions réseau surveillées🎜🎜
      rrreee🎜🎜Événements de fichiers🎜🎜🎜Reids n'utilise pas directement l'API epoll, mais la prend en charge en même temps Les modèles de multiplexage d'E/S à temps 4 encapsulent les API de ces modèles. Ensuite, lors de la phase de compilation, le modèle de multiplexage d'E/S pris en charge par le système d'exploitation est vérifié, et quel modèle est décidé à réutiliser en fonction de la stratégie. 🎜🎜En prenant également epoll comme exemple, Redis est encapsulé comme suit🎜rrreee🎜Rappelez-vous la structure eventLoop mentionnée ci-dessus, son membre apidata pointe vers 4 types d'objets de modèle de multiplexage d'E/S Stockez l'événement ; tableau qui doit être surveillé et utilise le descripteur de fichier socket comme index du tableau pour accéder aux éléments ; Fired stocke le tableau d'événements déclenchés. 🎜🎜La structure de l'événement de fichier est définie comme suit : 🎜rrreee🎜Regardez l'implémentation de l'événement de création de fichier aeCreateFileEvent🎜rrreee🎜Le serveur Redis gérera les transactions en créant divers événements de fichier, tels que : 🎜🎜🎜Créer un socket au démarrage et écoutez, attendez la connexion du client🎜
    rrreee🎜🎜Une fois que le client a établi une connexion socket avec le serveur, le serveur attendra la demande de commande du client🎜rrreee🎜🎜Une fois que le serveur aura traité la demande du client demande de commande, la réponse de la commande sera temporairement mise en cache dans Le tampon buf de la structure client n'enverra pas réellement de réponse de commande au client jusqu'à ce que l'événement inscriptible du descripteur de fichier client se produise🎜rrreee🎜Redis Tous les événements sont exécutés via la fonction aeProcessEvents pour contrôler. Parmi eux, l'exécution des événements de fichier provoquera un blocage (epoll_wait). Si l'événement bloquant est trop long, cela gênera l'exécution des événements de temps (timing). Pour éviter cette situation, le temps d'attente passé lors de l'implémentation des événements de fichier, Il est obtenu en calculant le premier événement temporel survenu🎜rrreee🎜🎜Résumé🎜🎜🎜Jetons maintenant un aperçu global du processus de la commande correspondante du serveur Redis🎜🎜🎜🎜🎜La fonction aeMain planifie les événements de fichier et les événements temporels en appelant la fonction aeProcessEvents implémentée. Les informations relatives à l'événement sont enregistrées dans aeEventLoop. Tout d'abord, obtenez l'intervalle de temps d'exécution n de l'événement temporel le plus court via la fonction aeSearchNearestTimer, puis appelez la fonction aeApiPoll pour obtenir le socket surveillé, et enfin exécutez les fonctions de traitement d'événements rfileProc et wfileProc correspondant au socket, et enfin exécutez l'événement temporel fonction processTimeEvents . 🎜🎜Un événement de connexion client-serveur complet : 🎜🎜🎜🎜Le serveur écoute l'événement AE_READABLE du package Lorsque le client envoie une demande de connexion, un événement AE_READABLE est généré et défini. le client La fonction de traitement des événements et des demandes de commande AE_READABLE de l'interface (aeFileProc), le client peut envoyer une demande de commande au serveur 🎜🎜🎜🎜Le client envoie une demande de commande au serveur, le socket client générera un événement AE_READABLE, déclenchant la commande traitement Le serveur l'exécute et l'exécution de la commande générera une réponse de commande correspondante. Le serveur associe l'événement AE_WRITABLE du socket client à la fonction de traitement de réponse de commande (aeFileProc). Lorsque le client tente de lire la réponse de commande, le socket client. L'événement AE_WRITABLE sera généré, déclenchant l'exécution du processeur de réponse de commande. Lorsque le processeur de réponse de commande écrit toutes les réponses de commande sur le socket, le serveur contactera la connexion entre l'événement AE_WRITABLE du socket client et la fonction de traitement de réponse de commande. (aeFileProc).<p>Pour plus de connaissances sur la programmation, veuillez visiter : <a href="https://www.php.cn/course.html" target="_blank" textvalue="编程视频">Vidéo de programmation</a> ! ! </p>

    Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

    source:juejin.cn
    Déclaration de ce site Web
    Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
    Tutoriels populaires
    Plus>
    Derniers téléchargements
    Plus>
    effets Web
    Code source du site Web
    Matériel du site Web
    Modèle frontal