当前位置: 首页 > news >正文

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

在这里插入图片描述

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;elseeventLoop->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_WRITABLEint 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)
{// 校验fdif (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一般都只有一个时间事件
在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述

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

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • RapidMiner数据挖掘4 —— 决策树
  • 深入理解MySQL分区技术
  • 工业烤箱设备厂家:专业制造,助力工业发展
  • Java-开发技巧
  • hcache缓存查看工具
  • 力扣1482.制作m束花所需的最少时间
  • MySQL 示例数据库大全
  • VUE FLV初次黑屏,deferLoadAfterSourceOpen参数作怪
  • 【江湖】离职经验之人在江湖
  • 【vue-9】购物车案例
  • AWS无服务器 应用程序开发—第七章 邮件服务 发布订阅(Amazon SES)
  • 蓝桥杯软件赛Java研究生组/A组)第二章基础算法-第三节:倍增
  • 7.Nginx动静分离
  • 为什么电容两端电压不能突变
  • 关于Ubuntu24.04嘉立创EDA无法启动的问题
  • @jsonView过滤属性
  • 0基础学习移动端适配
  • CentOS 7 防火墙操作
  • CSS魔法堂:Absolute Positioning就这个样
  • ES6 ...操作符
  • Java 23种设计模式 之单例模式 7种实现方式
  • Java程序员幽默爆笑锦集
  • java取消线程实例
  • jdbc就是这么简单
  • JS 面试题总结
  • JS笔记四:作用域、变量(函数)提升
  • overflow: hidden IE7无效
  • Yii源码解读-服务定位器(Service Locator)
  • Zepto.js源码学习之二
  • 深度学习在携程攻略社区的应用
  • 小程序01:wepy框架整合iview webapp UI
  • 应用生命周期终极 DevOps 工具包
  • PostgreSQL 快速给指定表每个字段创建索引 - 1
  • # 数据结构
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #java学习笔记(面向对象)----(未完结)
  • #经典论文 异质山坡的物理模型 2 有效导水率
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (1)常见O(n^2)排序算法解析
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (Demo分享)利用原生JavaScript-随机数-实现做一个烟花案例
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (顺序)容器的好伴侣 --- 容器适配器
  • (一)Kafka 安全之使用 SASL 进行身份验证 —— JAAS 配置、SASL 配置
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • *算法训练(leetcode)第四十五天 | 101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104. 建造最大岛屿
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .Net Core中Quartz的使用方法
  • .NET Framework杂记
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • .NET与java的MVC模式(2):struts2核心工作流程与原理
  • .NET中分布式服务