Redis源码剖析和注释(十九)--- Redis 事件处理实现

Redis 事件处理实现

1. Redis事件介绍

Redis服务器是一个事件驱动程序。下面先来简单介绍什么是事件驱动。

所谓事件驱动,就是当你输入一条命令并且按下回车,然后消息被组装成Redis协议的格式发送给Redis服务器,这就会产生一个事件,Redis服务器会接收该命令,处理该命令和发送回复,而当你没有与服务器进行交互时,那么服务器就会处于阻塞等待状态,会让出CPU从而进入睡眠状态,当事件触发时,就会被操作系统唤醒。事件驱动使CPU更高效的利用。

事件驱动是一种概括和抽象,也可以称为I/O多路复用(I/O multiplexing),它的实现方式各个系统都不同,一会会说到Redis的方式。

redis服务器中,处理了两类事件:

  • 文件事件(file event)Redis服务器通过套接字于客户端(或其他Redis服务器)进行连接,而文件事件就是服务器对套接字操作的抽象。
  • 时间事件(time event):Redis服务器的一些操作需要在给定的事件点执行,而时间事件就是服务器对这类定时操作的抽象。

2. 事件的抽象

Redis将这两个事件分别抽象成一个数据结构来管理。redis 所有源码注释

2.1 文件事件结构

/* File event structure */
typedef struct aeFileEvent {
    // 文件时间类型:AE_NONE,AE_READABLE,AE_WRITABLE
    int mask; /* one of AE_(READABLE|WRITABLE) */
    // 可读处理函数
    aeFileProc *rfileProc;
    // 可写处理函数
    aeFileProc *wfileProc;
    // 客户端传入的数据
    void *clientData;
} aeFileEvent;  //文件事件

其中rfileProcwfileProc成员分别为两个函数指针,他们的原型为

typedef void aeFileProc(struct aeEventLoop *eventLoop, int fd, void *clientData, int mask);

这个函数是回调函数,如果当前文件事件所指定的事件类型发生时,则会调用对应的回调函数处理该事件。函数指针与回调函数详解

当事件就绪时,我们需要知道文件事件的文件描述符还有事件类型才能对于锁定该事件,因此定义了aeFiredEvent结构统一管理:

/* A fired event */
typedef struct aeFiredEvent {
    // 就绪事件的文件描述符
    int fd;
    // 就绪事件类型:AE_NONE,AE_READABLE,AE_WRITABLE
    int mask;
} aeFiredEvent; //就绪事件

2.2 时间事件结构

/* Time event structure */
typedef struct aeTimeEvent {
    // 时间事件的id
    long long id; /* time event identifier. */
    // 时间事件到达的时间的秒数
    long when_sec; /* seconds */
    // 时间事件到达的时间的毫秒数
    long when_ms; /* milliseconds */
    // 时间事件处理函数
    aeTimeProc *timeProc;
    // 时间事件终结函数
    aeEventFinalizerProc *finalizerProc;
    // 客户端传入的数据
    void *clientData;
    // 指向下一个时间事件
    struct aeTimeEvent *next;
} aeTimeEvent;  //时间事件

从这个结构中可以看出,时间事件表是一个链表,因为它有一个next指针域,指向下一个时间事件。

和文件事件一样,当时间事件所指定的事件发生时,也会调用对应的回调函数,结构成员timeProcfinalizerProc都是回调函数,函数原型如下:函数指针与回调函数详解

typedef int aeTimeProc(struct aeEventLoop *eventLoop, long long id, void *clientData);
typedef void aeEventFinalizerProc(struct aeEventLoop *eventLoop, void *clientData);

虽然对文件事件和时间事件都做了抽象,Redis仍然需要对事件做整体抽象,于是定义了aeEventLoop结构。

2.3 事件状态结构

/* State of an event based program */
typedef struct aeEventLoop {
    // 当前已注册的最大的文件描述符
    int maxfd;   /* highest file descriptor currently registered */
    // 文件描述符监听集合的大小
    int setsize; /* max number of file descriptors tracked */
    // 下一个时间事件的ID
    long long timeEventNextId;
    // 最后一次执行事件的时间
    time_t lastTime;     /* Used to detect system clock skew */
    // 注册的文件事件表
    aeFileEvent *events; /* Registered events */
    // 已就绪的文件事件表
    aeFiredEvent *fired; /* Fired events */
    // 时间事件的头节点指针
    aeTimeEvent *timeEventHead;
    // 事件处理开关
    int stop;
    // 多路复用库的事件状态数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值