redis03 补充 redis驱动模型:事件驱动

news2024/11/23 13:06:38

在这里插入图片描述

1.文件事件(重点)文件事件就是服务器对socket操作的抽象,Redis服务器通过监听并处理这些socket产生的文件事件,实现对客户端调用的响应
在这里插入图片描述

1.1 文件事务处理器的构成

1.2 IO多路复用
在这里插入图片描述
在这里插入图片描述
注:
epoll是linux系统的底层IO多路复用技术
kqueue是mac系统的底层IO多路复用技术

redis对这些函数进行了封装,形成一个ae.c的文件,这个文件掩盖了不同操作系统底层的差异。Redis封装的接口定义如下:

typedef struct aeApiState {
    // epoll实例描述符
    int epfd;
    // 绑定的事件
    struct epoll_event *events;
} aeApiState;

/**
 * 创建epoll 
 */
static int aeApiCreate(aeEventLoop *eventLoop)

/**
 * 调整绑定事件的大小
 */
static int aeApiResize(aeEventLoop *eventLoop, int setsize)

/**
 * 释放epoll
 */
static void aeApiFree(aeEventLoop *eventLoop)

/**
 * 绑定新事件
 */
static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask)

/**
 * 删除事件
 */
static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask)

/**
 * 获取可执行事件
 */
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp)

在linux中,一般使用 Epoll 中,Epoll 就是事件通知器,可以向 Epoll 注册我们感兴趣的事件。一般这里的IO多路复用技术可以认为是Epoll,Epoll会把事件传递到 事件分发器

1.3事务分发器

事务分发器一般有两种,一种是文件分发器,一种是时间分发器。这里讲的是文件事件,所以一般用文件事务分发器来描述:

文件事件分发的事件分发器
ae.c中aeProcessEvents实现了事件分发器的功能,文件事件分发的核心代码如下:

// I/O多路复用,当有事件发生或者超时才返回
// 调用操作系统函数实现,在Linux上为epoll
numevents = aeApiPoll(eventLoop, tvp);

/* After sleep callback. */
if (eventLoop->aftersleep != NULL && flags & AE_CALL_AFTER_SLEEP)
    eventLoop->aftersleep(eventLoop);

// 遍历发生的事件
for (j = 0; j < numevents; j++) {
    aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j].fd];
    int mask = eventLoop->fired[j].mask;
    int fd = eventLoop->fired[j].fd;
    int fired = 0;
    int invert = fe->mask & AE_BARRIER;

    // 处理读事件
    if (!invert && fe->mask & mask & AE_READABLE) {
        fe->rfileProc(eventLoop,fd,fe->clientData,mask);
        fired++;
    }

    // 处理写事件
    if (fe->mask & mask & AE_WRITABLE) {
        if (!fired || fe->wfileProc != fe->rfileProc) {
            fe->wfileProc(eventLoop,fd,fe->clientData,mask);
            fired++;
        }
    }

    // 如果颠倒,那么此时处理读事件
    if (invert && fe->mask & mask & AE_READABLE) {
        if (!fired || fe->wfileProc != fe->rfileProc) {
            fe->rfileProc(eventLoop,fd,fe->clientData,mask);
            fired++;
        }
    }

    processed++;
}

时间事件处理的核心代码如下:

static int processTimeEvents(aeEventLoop *eventLoop) {
    int processed = 0;
    aeTimeEvent *te;
    long long maxId;
    time_t now = time(NULL);

    // 处理系统时间被修改的情况
    if (now < eventLoop->lastTime) {
        te = eventLoop->timeEventHead;
        while(te) {
            te->when_sec = 0;
            te = te->next;
        }
    }
    // 更新上一次执行的时间
    eventLoop->lastTime = now;

    te = eventLoop->timeEventHead;
    maxId = eventLoop->timeEventNextId-1;
    // 遍历时间事件链表
    while(te) {
        long now_sec, now_ms;
        long long id;

        // 删除标记为删除状态的时间事件
        if (te->id == AE_DELETED_EVENT_ID) {
            aeTimeEvent *next = te->next;
            if (te->prev)
                te->prev->next = te->next;
            else
                eventLoop->timeEventHead = te->next;
            if (te->next)
                te->next->prev = te->prev;
            if (te->finalizerProc)
                te->finalizerProc(eventLoop, te->clientData);
            zfree(te);
            te = next;
            continue;
        }

        // 如果时间事件ID大于maxId,说明该时间事件是本次遍历过程中产生的,本次遍历不处理
        if (te->id > maxId) {
            te = te->next;
            continue;
        }
        // 获取当前时间
        aeGetTime(&now_sec, &now_ms);
        if (now_sec > te->when_sec ||
            (now_sec == te->when_sec && now_ms >= te->when_ms))
        {
            // 找到需要处理的时间事件
            int retval;

            id = te->id;
            // 执行对应的时间事件处理函数
            retval = te->timeProc(eventLoop, id, te->clientData);
            processed++;
            if (retval != AE_NOMORE) {
                // 刷新该时间事件下一次执行时间
                aeAddMillisecondsToNow(retval,&te->when_sec,&te->when_ms);
            } else {
                // 不再需要,则标记为删除状态
                te->id = AE_DELETED_EVENT_ID;
            }
        }
        // 继续下一个时间事件,直到链表结束
        te = te->next;
    }
    return processed;
}

1.4 文件事件的结构

在这里插入图片描述

typedef struct aeFileEvent {
    // 监听事件类型掩码,可表示为事件类型
    // 值可以是 AE_READABLE 或 AE_WRITABLE ,
    // 或者 AE_READABLE | AE_WRITABLE
    int mask; /* one of AE_(READABLE|WRITABLE) */

    // 读事件处理器
    aeFileProc *rfileProc;

    // 写事件处理器
    aeFileProc *wfileProc;

    // 多路复用库的私有数据
    void *clientData;
} aeFileEvent;

// 文件事件处理器
typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);

1.5 主要是第一个函数createFileEvent,用于绑定文件事件

int aeCreateFileEvent(aeEventLoop *eventLoop, int fd, int mask,
        aeFileProc *proc, void *clientData)
{
    // 校验fd
    if (fd >= eventLoop->setsize) {
        errno = ERANGE;
        return AE_ERR;
    }

    // 准备填充该FD对应的处理
    aeFileEvent *fe = &eventLoop->events[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;
    if (fd > eventLoop->maxfd)
        eventLoop->maxfd = fd;
    return AE_OK;
}

在这里插入图片描述在这里插入图片描述

在这里插入图片描述
1.6最终事件处理器来执行事件
在这里插入图片描述
1.6.1
在这里插入图片描述在这里插入图片描述

1.6.2
在这里插入图片描述
1.6.3在这里插入图片描述1.6.4

在这里插入图片描述在这里插入图片描述

2.时间事件
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

typedef struct aeTimeEvent {
    // 时间事件的唯一标识符
    long long id; /* time event identifier. */

    // 事件的到达时间
    long when_sec; /* seconds */
    long when_ms; /* milliseconds */

    // 事件处理函数
    aeTimeProc *timeProc;

    // 事件终结函数
    aeEventFinalizerProc *finalizerProc;

    // 多路复用库的私有数据
    void *clientData;

    // 指向上个时间事件结构,形成链表
    struct aeTimeEvent *prev;

    // 指向下个时间事件结构,形成链表
    struct aeTimeEvent *next;
} aeTimeEvent;

// 时间事件处理器
typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);
// 时间事件终结处理器
typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);

在这里插入图片描述
举个例子:

在这里插入图片描述

说明一下,链表是无序的
在这里插入图片描述
此时的redis一般都只有一个时间事件
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述在这里插入图片描述在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1817805.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos8 中文打印报错,解决

sudo yum install -y glibc-locale-source sudo localedef -c -f UTF-8 -i zh_CN zh_CN.UTF-8 sudo yum install -y fontconfig

vlc多媒体播放器(支持各种本地视频、网络视频、音频及摄像头直播地址)winform(支持全屏)自动适应x86、x64平台插件及重要代码

1、学习vlcControl1及libvlc.dll类方法(x86为例)最新v3.0.21 1.1 本博文以控件(vlcControl1)方式为主介绍 1.2 安装-引用,添加控件到窗体 using Vlc.DotNet.Forms; 1.3 窗体布局、编写代码 打开文件(以本地媒体文件为主)打开地址(以网络媒体地址为主)播放|暂停功能停…

C# WPF入门学习番外篇(二) —— C# WPF使用数据库创建注册登录界面

C# WPF入门学习番外篇&#xff08;二&#xff09; —— C# WPF使用数据库创建注册登录界面 在这篇番外篇博客中&#xff0c;我们将介绍如何在C# WPF应用程序中使用数据库来创建一个简单的注册和登录界面。通过本教程&#xff0c;你将学习到如何在WPF中与数据库进行交互&#xf…

提高SOA噪声系数和饱和功率的方法

----翻译自Kevin Carney, Robert Lennox等人撰写的文章 摘要 针对多触点体半导体光放大器&#xff08;SOA&#xff09;&#xff0c;使用速率方程模型研究了有源层纵向载流子密度分布特性。结果表明&#xff0c;噪声系数和饱和输出光功率都可以通过偏置电流分布进行优化。本文还…

Apache HttpClient总览

一、重大版本 Apache HttpClient 4.x 系列 • HttpClient 4.0&#xff08;发布于2008年左右&#xff09;&#xff1a;这是一个重要的里程碑&#xff0c;标志着HttpClient从Jakarta Commons项目转移到Apache HttpComponents项目。4.0版进行了大量的重构&#xff0c;引入了新…

Turbo Console Log自定义配置

写log太麻烦了&#xff1f;可以用下vscode中的Turbo Console Log的插件 因为vscode的其他快捷键可能会和这个插件产生冲突&#xff0c;所以可以从这里设置自定义不重复的快捷键。我这里用的shiftaltG用来生成log 我用的是显示第多少行和路径名 效果&#xff1a; 还有其他的…

从爱好到收入AI贴纸变现的五种途径,你尝试过几种?你会制作吗?

一、AI贴纸变现方式&#xff1a; 贴纸变现的方式主要包括以下几种&#xff1a; 1、广告变现 通过在小红书、公众号等可发图文的自媒体平台发布你制作的可爱贴纸&#xff0c;从而实现对可爱贴纸喜爱的人士观看并成为你的粉丝。粉丝达到一定数量即可接商业广告变现。 2、电商变…

js算法 计算每一列的平均值 求matrix数组对应列的平均值 组成一个新的数组 matrix数组有6行 如果某一行里的值是0则不纳入平均的分母里

let matrix [[18.95, 21.1, 0, 23, 0, 0, 0],[19, 25.3, 24.64, 0, 0, 0, 21.24],[22.18, 24.5, 20, 0, 26, 0, 0],[18.41, 19.05, 22.41, 27.67, 17, 0, 0],[14.86, 19.31, 0, 19.4, 18.71, 0, 25.04],[18.93, 19.53, 0, 0, 0, 0, 0] ];// 获取矩阵的列数 const numCols mat…

网络安全等级保护基本要求解读- 安全计算环境-应用系统和数据安全

概述 越来越多的企业用户已将核心业务系统转移到网络上&#xff0c;Web浏览器成为业 务系统的窗口&#xff0c;应用系统面临更多的安全威胁&#xff1b;并且由于各种原因使得其 存在较多的安全漏洞。 在此背景下&#xff0c;如何保障企业的应用安全&#xff0c;尤其是Web应用…

现场直击 | 飞凌嵌入式亮相2024上海国际嵌入式展

6月12日&#xff0c;2024上海国际嵌入式展&#xff08;embedded world China 2024&#xff09;在上海世博展览馆开幕。飞凌嵌入式亮相3号馆646展位&#xff0c;聚焦人工智能、智慧交通、工业互联网、智慧医疗、电力与储能等领域&#xff0c;旨在为全球客户带来一场技术与创新的…

MySQL第二种实现方式:现在有一个生产计划,甲乙丙3个品类共16个产品,生产时间6天,每天甲品类可以生产1张单,乙3张,丙1张,请用MySQL写出H列的效果

接上篇&#xff1a;链接: 现在有一个生产计划&#xff0c;甲乙丙3个品类共16个产品&#xff0c;生产时间6天&#xff0c;每天甲品类可以生产1张单&#xff0c;乙3张&#xff0c;丙1张&#xff0c;请用MySQL写出H列的效果 第二种写法&#xff1a; -- 使用WITH子句创建CTE WITH…

《500 Lines or Less》(4)Contingent: A Fully Dynamic Build System(构建系统)

介绍 构建系统长期以来一直是计算机编程中的标准工具。 标准 make 构建系统由其作者获得 ACM 软件系统奖&#xff0c;于 1976 年首次开发。它不仅允许您声明一个输出文件依赖于一个&#xff08;或多个&#xff09;输入文件&#xff0c;而且可以递归地执行此操作。例如&#xf…

MySQL(5)

聚合函数 GROUP BY 的使用 需求&#xff1a;查询各个部门的平均工资&#xff0c;最高工资SELECT department_id,AVG(salary),SUM(salary)FROM employeesGROUP BY department_id;需求&#xff1a;查询各个job_id的平均工资SELECT job_id,AVG(salary)FROM employeesGROUP BY jo…

LabVIEW Actor架构特点与适用范围

LabVIEW的Actor架构提供了一种基于消息传递的并行任务管理方式&#xff0c;适合复杂系统的模块化设计。其特点包括高可扩展性、灵活的消息传递和并行处理能力。维护和修改要求较高&#xff0c;适合有一定经验的开发人员。对于中小型项目&#xff0c;可考虑选择更简单的状态机架…

使用winscp 通过中转机器(跳板机、堡垒机)密钥远程连接服务器,保姆级别教程

1.winscp下载地址 winscp下载 2.安装自己选择位置 3.连接服务器 到这里,基本就是没有壁垒机的就可直接连接,传递文件 4.配置中转服务器(壁垒机、跳板机) 选择高级选项 配置utf-8的编码格式 配置中转服务器(壁垒机、跳板机) 设置中专机的密码或者私钥 配置私钥

Vue3使用datav3报错问题解决

报错&#xff1a;Failed to resolve entry for package "dataview/datav-vue3". The package may have incorrect main/module/exports specified in its package.json. 修改package.json 修改为 "module": "./es/index.mjs",

《一头扎进》系列之Python+Selenium框架设计篇22- 价值好几K的框架,狼来了,狼来了....,狼没来,框架真的来了

宏哥微信粉丝群&#xff1a;https://bbs.csdn.net/topics/618423372 有兴趣的可以扫码加入 1. 简介 前边宏哥一边一边的喊框架&#xff0c;就如同一边一边的喊狼来了&#xff01;狼来了&#xff01;.....这回是狼没有来&#xff0c;框架真的来了。从本文开始宏哥将会一步一步介…

Django+Vue.js怎么实现搜索功能

一.前言 类似这样的搜索功能 二.前端代码 <div class"form-container"><div class"form-group"><label for"departure-city">出发城市</label><select v-model"departureCity" id"departure-city&q…

CentOS系统停服进入倒计时,用户该如何应对?

本月30日&#xff0c;CentOS 7将正式停服。 凭借开源免费、稳定、硬件兼容性等特性&#xff0c;CentOS深受中国乃至全世界厂商、开发者和用户的青睐&#xff0c;应用范围极为广泛。 停服停更&#xff0c;对于广大用户来说也是一项巨大的考验&#xff0c;这意味着用户将无法获得…

【web APIs】快速上手Day02

文章目录 Web APIs - 第2天事件事件监听案例一 :京东点击关闭顶部广告案例二&#xff1a;随机点名案例拓展知识-事件监听版本 双击事件 事件类型鼠标事件综合案例-轮播图完整版 焦点事件综合案例-小米搜索框案例 键盘事件文本事件 事件对象综合案例-按下回车发布评论 环境对象回…