閱讀551 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Redis中的事件處理模型

Redis並沒有使用libevent,libev,libuv等事件IO庫,而是通過ae.h、ae.c兩個文件,封裝了簡單的事件處理模型。進一步地,事件處理需要使用到係統的select、epoll等函數,在ae.c中,通過簡單的宏判斷,引入相應的實現文件,分別是ae_epoll.c、ae_evport.c、ae_kqueue.c和ae_select.c。

先來看下ae.h。首先,Redis定義了兩種事件類型,分別是aeFileEventaeTimeEvent,前者針對文件IO(包含網絡)。後者主要是一些定時或周期運行的函數,比如serverCron()

最主要的數據結構是struct aeEventLoop。ae.h對外提供的方法,幾乎都以此結構的實例為操作對象。

typedef struct aeEventLoop {
    int maxfd;   /* highest file descriptor currently registered */
    int setsize; /* max number of file descriptors tracked */
    long long timeEventNextId;
    time_t lastTime;     /* Used to detect system clock skew */
    aeFileEvent *events; /* Registered events */
    aeFiredEvent *fired; /* Fired events */
    aeTimeEvent *timeEventHead;
    int stop;
    void *apidata; /* This is used for polling API specific data */
    aeBeforeSleepProc *beforesleep;
    aeBeforeSleepProc *aftersleep;
} aeEventLoop;

maxfd記錄當前跟蹤的最大文件描述符,在調用某些api時便於使用,比如select()需要給一個maxfd+1的參數。

setsize是能處理的文件描述符的最大數量。後麵可以看到這個數量關係到eventsfired的內存分配大小。

另外一個比較重要的是apidata,其實是指向了具體的事件處理模型相關的一個狀態數據(aeApiState)。如果使用的是select,那麼狀態數據包含了不同的fd_set;如果使用的是epoll,狀態數據包含了epoll_create()返回的fd,還有用於接收epoll_wait()返回的存在可用事件的列表events。

aeCreateEventLoop()便是創建aeEventLoop的實例。在這裏可以看到,針對文件IO,eventsfired是通過固定連續分配,按照數組的方式來使用。針對時間事件,則是timeEventHead這樣的一個鏈表。

另外,再通過調用aeApiCreate()來這是apidata。按照使用的不同的係統事件處理機製,aeApiCreate()的實現是不同的。取決於如下這段代碼:

#ifdef HAVE_EVPORT
#include "ae_evport.c"
#else
    #ifdef HAVE_EPOLL
    #include "ae_epoll.c"
    #else
        #ifdef HAVE_KQUEUE
        #include "ae_kqueue.c"
        #else
        #include "ae_select.c"
        #endif
    #endif
#endif

一般來說,這些HAVE_開頭的宏,是通過configure(GNU autoconf automake係統工具生成),或者cmake判斷當前係統環境並進行定義的。但是Redis並沒有使用什麼複雜的構建工具,隻有一個Makefile,這些宏是在src/config.h中,根據操作係統或編譯器提供的宏進行判斷並進行定義。

具體調用的地方,比如src/server.c中,先進行

server.el = aeCreateEventLoop(server.maxclients+CONFIG_FDSET_INCR);

創建了aeEventLoop

之後便可以注冊定時任務:

if (aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL) == AE_ERR) {
        serverPanic("Can't create event loop timers.");
        exit(1);
    }

最後更新:2017-09-25 16:33:55

  上一篇:go  用超級瑪麗理解機器學習基礎
  下一篇:go  網狐6.6源碼下載搭建之自動更新模塊教程