1. 程式人生 > 其它 >事件 - 《Redis設計與實現》讀書筆記

事件 - 《Redis設計與實現》讀書筆記

Redis伺服器是一個事件驅動程式,伺服器處理的事件分為時間事件檔案事件兩種型別

檔案事件

伺服器對套接字操作的抽象
Redis伺服器通過套接字與客戶端(或者其他Redis伺服器)進行連線
伺服器與客戶端(或者其他伺服器)的通訊會產生相應的檔案事件,而伺服器則通過監聽並處理這些事件來完成一系列網路通訊操作

  • 組成
/* File event structure */
typedef struct aeFileEvent {
    // 檔案事件類別:AE_READABLE、AE_WRITABLE、AE_BARRIER
    // 當客戶端對套接字執行connect、寫入write、關閉close操作,產生AE_READABLE事件
    // 當客戶端對套接字執行read操作,產生AE_WRITABLE事件 
    // 如果一個套接字又可讀又可寫的話,那麼伺服器將先讀套接字,後寫套接字
    int mask;
    

    // 檔案事件讀處理器
    aeFileProc *rfileProc;
    
    // 檔案事件寫處理器
    aeFileProc *wfileProc;

    void *clientData;
} aeFileEvent;

檔案事件處理器

  • 基於Reactor模式實現的網路通訊程式

  • 實現原理
    使用I/O多路複用程式同時監聽多個套接字,
    當被監聽的套接字準備好執行連線應答accept、讀取read、寫入write、關閉close等操作時,與操作相對應的檔案事件就會產生,
    將所有產生事件的套接字都放到一個佇列裡面,通過這個佇列,以阻塞、有序、同步、每次一個的方式向檔案事件分派器傳送套接字,
    經過檔案事件分派器進行分發,根據套接字目前執行的任務來為套接字關聯不同的事件處理器

  • 組成

    • 套接字
    • I/O多路複用程式:evport、epoll、kqueue、select
      自動選擇系統中效能最高的I/O多路複用函式庫作為底層
    #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
    
    • 檔案事件分派器:src/ae.c/aeProcessEvents
    • 事件處理器
      • 連線應答處理器:src/networking.c/acceptTcpHandler
      • 命令請求處理器:src/networking.c/readQueryFromClient
      • 命令回覆處理器:src/networking.c/sendReplyToClient

時間事件

伺服器在一般情況下只執行serverCron函式這一個週期性時間事件

實現原理:伺服器將所有時間事件都放在一個無序連結串列(不按when屬性的大小排序)中,每當時間事件執行期執行時,遍歷整個連結串列,查詢所有已到達的時間事件,並呼叫相應的事件處理器

  • 組成
typedef struct aeTimeEvent {
    // 全域性唯一標識號ID,ID
    long long id; 

    // 時間事件的到達事件,單位為微秒
    monotime when; 
    
    // 時間事件處理器
    aeTimeProc *timeProc; 

    aeEventFinalizerProc *finalizerProc;
    void *clientData;
    struct aeTimeEvent *prev;
    struct aeTimeEvent *next;
    int refcount; 
} aeTimeEvent;
  • 分類
    • 定時事件:事件處理器返回src/ae.h/AE_NOMORE值
    • 週期性事件:事件處理器返回不是src/ae.h/AE_NOMORE值

事件的排程與執行規則

  1. 檔案事件和時間事件之間是合作關係,伺服器會輪流處理這兩種事件,並且處理事件的過程中不會進行搶佔
  2. 對檔案事件和時間事件的處理都是同步、有序、原子地執行的,伺服器不會中途中斷事件處理,也不會對事件進行搶佔
  3. 時間事件的實際處理事件通常會比設定的到達時間晚一些,主要因為時間事件在檔案事件之後執行
隻言片語任我說,提筆句句無需忖。落筆不知寄何人,唯有邀友共斟酌。