接下來的三篇文章将對Redis的網絡監聽流程及涉及到事件庫和各個主要方法進行介紹。
在介紹 redis的網絡監聽流程和事件庫之前,我們先設想一下,如果我們不采用
libevent等流行的開源庫進行基于事件的網絡監聽,而是自己去實作一套基于事件的庫去進行網絡監聽,需要考慮些什麼,然後我們帶着這些問題去分析 Redis是如果通過少量的代碼來完成這個工作的。
在我認為,需要考慮的問題有以下一些(限于水準,暫時隻能想到這些

):
1.
采用何種 事件觸發機制 ,是 epoll, select, kquque,抑或 3種都支援
2.
支援那些事件?
3.
如何管理各種事件(資料結構 —響應,查找)?
4.
如何響應 I/O事件?是異步還是同步?是單線程響應還是多線程響應?
5.
如何盡快地響應各種事件?
Redis的作者沒有采用 libevent等之類的知名網絡庫,而是通過少量的代碼實作了一個基于反轉模式的輕量級網絡庫,對于這一點, Redis的作者是這樣解釋的,因為他覺得 libevent之類的知名網絡庫太過于龐大,而對 Redis來說隻需要異步監聽的基本功能,是以他不想引入過于“龐大”的第三庫。
首先我們從 ae.h檔案開始,介紹一下 redis網絡監聽所涉及的幾個結構體和方法
C代碼
- /* A fired event */
- typedef struct aeFiredEvent {
- int fd;
- int mask;
- } aeFiredEvent;
- /* State of an event based program */
- typedef struct aeEventLoop {
- int maxfd;
- long long timeEventNextId;
- aeFileEvent events[AE_SETSIZE]; /* Registered events */
- aeFiredEvent fired[AE_SETSIZE]; /* Fired events */
- aeTimeEvent *timeEventHead;
- int stop;
- void *apidata; /* This is used for polling API specific data */
- aeBeforeSleepProc *beforesleep;
- } aeEventLoop;
/* A fired event */
typedef struct aeFiredEvent {
int fd;
int mask;
} aeFiredEvent;
/* State of an event based program */
typedef struct aeEventLoop {
int maxfd;
long long timeEventNextId;
aeFileEvent events[AE_SETSIZE]; /* Registered events */
aeFiredEvent fired[AE_SETSIZE]; /* Fired events */
aeTimeEvent *timeEventHead;
int stop;
void *apidata; /* This is used for polling API specific data */
aeBeforeSleepProc *beforesleep;
} aeEventLoop;
aeEventLoop 是用于網絡循環監聽一個結構體,其通過 events這個内部數組來維護要要監聽的檔案事件,通過 fired來維護 select到需要響應的檔案事件, timeEventHead則是把定時響應的時間事件通過連結清單的形式維護起來。
aeFileEvent是檔案讀寫事件的抽象
- /* File event structure */
- typedef struct aeFileEvent {
- int mask; /* one of AE_(READABLE|WRITABLE) */用來區分讀寫事件
- aeFileProc *rfileProc; 讀檔案事件的處理函數
- aeFileProc *wfileProc; 寫檔案事件的處理函數
- void *clientData;
- } aeFileEvent;
- aeTimeEvent則是定時響應的事件的抽象
- /* Time event structure */
- typedef struct aeTimeEvent {
- long long id; /* time event identifier. */
- long when_sec; /* seconds */ 事件響應點的秒時刻
- long when_ms; /* milliseconds */事件響應的毫秒時刻
- aeTimeProc *timeProc; 事件響應函數
- aeEventFinalizerProc *finalizerProc;
- struct aeTimeEvent *next; 下一個要響應的時間事件
- } aeTimeEvent
/* File event structure */
typedef struct aeFileEvent {
int mask; /* one of AE_(READABLE|WRITABLE) */用來區分讀寫事件
aeFileProc *rfileProc; 讀檔案事件的處理函數
aeFileProc *wfileProc; 寫檔案事件的處理函數
void *clientData;
} aeFileEvent;
aeTimeEvent則是定時響應的事件的抽象
/* Time event structure */
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 *next; 下一個要響應的時間事件
} aeTimeEvent
在 Redis的網絡監控庫裡面,
、 aeFileEvent和 aeTimeEvent之間的關系是:
在了解了 Redis基于事件驅動的網絡庫所涉及的三個基本元件後,我們來看一下 Redis的網絡監聽的基本流程: