Redis——事件

問題:
    Redis 是單線程的,怎麼實現的多個客戶端的鏈接訪問?服務器

    Redis服務器是一個事件驅動程序,服務器須要處理一下兩類事件:
    * 文件事件(file event): Redis服務器經過套接字與客戶端(或者其餘Redis服務器)進行鏈接,而文件事件就是服務器對套接字操做的抽象。服務器與客戶端(或者其餘服務器)的通訊會產生相應的文件事件,而服務器則經過監聽並處理這些事件來完成一系列網絡通訊操做。
    
    * 時間事件(time event):Redis服務器中的一些操做(好比 serverCon)函數須要在給定的時間點執行,而時間事件就是服務器對這類定時操做的抽象。網絡


文件事件
    Redis基於Reactor模式開發了本身的網絡事件處理器:這個處理器被稱爲文件事件處理器(five event handler)
    * 文件事件處理器使用I/O多路複用(multiplexing)程序來同時監聽多個套接字,並根據套接字目前執行的任務來爲套接字關聯不一樣的事件處理器。
    * 當監聽的套接字準備好執行鏈接應答(accept),讀取(read),寫入(write),關閉(close)等操做時,與操做相對應的文件事件就會產生,這時文件事件處理器就會調用套接字以前關聯好的事件處理器來處理這些事件。
    雖然文件事件處理器以單線程方式運行,但經過使用I/O多路複用程序來監聽多個套接字,文件事件處理器既實現了高性能的網絡通訊模型,又能夠很好地與Redis服務器中其餘一樣以單線程方式運行的模塊進行對接,這保持了Redis內部單線程設計的簡單性。併發

文件事件處理器的構成函數

    文件事件處理器的四個組成部分,它們分別是套接字,I/O多路複用程序,文件事件分派器(dispatcher),以及事件處理器。性能

文件事件是對套接字操做的抽象,每當一個套接字準備好執行鏈接應答(accept),寫入,讀取,關閉等操做時,就會產生一個文件事件。由於一個服務器一般會鏈接多個套接字,因此多個文件事件有可能會併發地出現。spa

    I/O 多路複用程序負責監聽多個套接字,並向文件事件分派器傳送那些產生了事件的套接字。線程

    儘管多個文件事件可能會併發地出現,但I/O多路複用程序老是會將全部產生事件的套接字都放在一個隊列裏面,而後經過這個隊列,以有序(sequentially)、同步(synchronoously)、每次一個套接字的方式向文件事件分派器傳送套接字。當上一個套接字產生的事件處理完畢以後(該套接字爲事件處理完畢),I/O多路複用程序纔會繼續向文件事件分派器傳送下一個套接字。設計

文件事件分派器接收I/O多路複用程序傳來的套接字,並根據套接字產生的事件的類型,調用相應的時間處理器。指針

 服務器會執行不一樣任務的套接字關聯不一樣的事件處理器,這些處理器是一個個函數,它們定義了某個事件發生時,服務器應該執行的動做。server

I/O多路複用程序的實現:


時間事件
 Redis的時間事件分爲如下兩類:
    * 定時事件:讓一段程序在指定的時間以後執行一次。好比說:讓程序X在當前時間的30毫秒以後執行一次。
    * 週期性事件:讓一段程序每隔指定時間就執行一次。好比說:讓程序Y每隔30毫秒就執行一次。
 一個時間事件主要由如下三個屬性組成:
    * id: 服務器爲時間事件建立的全局惟一ID(標識號)。ID號按從小到大的順序遞增,新事件ID號比舊事件的ID號要大。
    * when:毫秒精度的UNIX時間戳,記錄了時間事件的到達(arrive)時間。
    * timeproc: 時間事件處理器,一個函數。當時間事件到達時,服務器就會調用相應的處理器  來處理事件。
一個時間事件是定時器事件仍是週期性事件取決於時間事件處理器的返回值:
    * 若是事件處理器返回ae.h/AE_NOMORE,那麼這個事件爲定時事件:該事件在達到一次以後會被刪除,以後再也不到達。
    * 若是事件處理器返回一個非AE_NOMORE的整數值,那麼這個事件爲週期性事件:當一個時間事件到達以後,服務器會根據事件處理器返回的值,對時間事件的when屬性進行更新,讓這個事件在一段時間以後再次到達,並以這種方式一直更新並運行下去。好比說,若是一個時間事件的處理器函數返回整數值30,那麼服務器應該對這個事件進行更新,讓這個事件在30毫秒以後再次到達。


    實現:
    服務器將全部時間事件都放在一個無序鏈表中,每當時間事件執行器運行時,它就遍歷整個鏈表,查找全部已到達的時間事件,並調用相應的事件處理器。

                               無序列表並不影響時間事件處理器的性能
    在目前版本中,正常模式下的Redis服務器只使用serverCron一個時間事件,而在benchmark模式下,服務器也只使用兩個時間事件。這種狀況下,服務器幾乎是將無序鏈表退化成一個指針來使用,因此使用無序鏈表來保存時間事件,並不影響事件執行的性能。


總結     * Redis服務器是一個事件驅動程序,服務器處理的事件分爲時間事件和文件事件兩類。     * 文件事件處理器是基於Reactor模式實現的網絡通訊程序。     * 文件事件是對套接字操做的抽象:每次套接字變爲可應答(acceptable),可寫(writeable)或者可讀(readable)時,相應的文件事件就會產生。     * 文件事件分爲AE_READABLE(讀事件)和AE_WRITEABLE事件(寫事件)兩類。     * 事件時間能夠分爲定時事件和週期性事件:定時事件只在指定的時間到達一次,而週期性事件則每隔一段時間到達一次。     * 服務器在通常狀況下只執行serverCorn函數一個時間事件,而且這個事件是週期性事件。     * 文件事件和時間事件之間是合做關係,服務器會輪流處理這兩種事件,而且處理事件的過程當中也不會進行搶佔。     * 時間事件的實際處理時間一般會比設定的達到時間晚一些。

相關文章
相關標籤/搜索