深入聊聊 Redis 的事件
良心公眾號
關(guān)注不迷路
01
概述
Redis 服務(wù)器是一個事件驅(qū)動程序,需要處理兩類事件:
文件事件:Redis 服務(wù)器通過套接字與外部進行連接,而文件事件就是服務(wù)器對套接字操作的抽象。服務(wù)器與外部的通信會產(chǎn)生相應(yīng)的文件事件,服務(wù)器通過監(jiān)聽并處理這些事件來完成一系列網(wǎng)絡(luò)通信操作。
時間事件:Redis 服務(wù)器中的一些操作需要在給定的時間點執(zhí)行,而時間事件就是服務(wù)器對這類定時操作的抽象。
02
文件事件
Redis 基于 Reactor 模式開發(fā)了自己的網(wǎng)絡(luò)事件處理器——文件事件處理器。
文件事件處理器使用 I/O 多路復(fù)用程序來同時監(jiān)聽多個套接字,并根據(jù)套接字目前執(zhí)行的任務(wù)來為套接字關(guān)聯(lián)不同的事件處理器。
當(dāng)被監(jiān)聽的套接字準(zhǔn)備好執(zhí)行鏈接應(yīng)答,讀取,寫入,關(guān)閉等操作時,就會產(chǎn)生對應(yīng)的文件事件,文件事件處理器就會調(diào)用套接字之間關(guān)聯(lián)好的事件處理器來處理這些事件。
文件事件處理器可以拆分為四個部分:套接字、I/O 多路復(fù)用程序、文件事件分派器、事件處理器。具體工作如下圖所示:

從上圖可以看出,文件事件處理器的工作流程大致可以作如下描述:I/O 多路復(fù)用程序負責(zé)監(jiān)聽套接字,并將其存放至隊列中,然后按照有序、同步的方式逐一向文件事件分派器進行傳送,文件事件分派器接收到套接字之后,會根據(jù)套接字對應(yīng)的事件類型調(diào)用對應(yīng)的事件處理器。
Redis 的 I/O 多路復(fù)用程序的功能,是通過封裝下圖所示的多種 I/O 多路復(fù)用函數(shù)庫來實現(xiàn)的,程序在編譯時會根據(jù)當(dāng)前狀態(tài)選擇性能最高的函數(shù)庫。

Redis 的文件事件分派器會遍歷所有的事件,并調(diào)用相應(yīng)的事件處理器來對其進行處理。
文件事件處理器可分為連接應(yīng)答處理器、命令請求處理器、命令回復(fù)處理器。它們的具體作用場景如下所示:
連接應(yīng)答處理器:客戶端向服務(wù)端發(fā)起建立 socket 連接請求,監(jiān)聽套接字產(chǎn)生 AE_READABLE 事件,觸發(fā)連接應(yīng)答處理器執(zhí)行。
命令請求處理器:客戶端與服務(wù)器建立連接后,向服務(wù)器發(fā)送命令,客戶端套接字產(chǎn)生 AE_READABLE 事件,觸發(fā)命令請求處理器執(zhí)行。
命令回復(fù)處理器:當(dāng)服務(wù)器需要將命令回復(fù)回傳客戶端時,服務(wù)器會將客戶端套接字的 AE_WRITABLE 事件和命令回復(fù)處理器作關(guān)聯(lián),客戶端產(chǎn)生 AE_WRITABLE 事件,觸發(fā)命令回復(fù)處理器執(zhí)行。
上述過程可以用下圖簡化表示:

03
時間事件
Redis 的時間事件可分為定時事件和周期性事件,其含義如下:
定時事件:讓程序在一段時間之后執(zhí)行一次。
周期性事件:讓程序每隔一段時間執(zhí)行一次。
Redis 的一個時間事件主要由以下屬性構(gòu)成:
id:時間事件全局唯一的標(biāo)識號,從小到大遞增
when:時間事件的到達時間,毫秒精度的UNIX時間戳
timeProc:時間事件處理器,當(dāng)時間事件到達時,執(zhí)行該函數(shù)
服務(wù)器會將所有時間事件放入一個鏈表中,當(dāng)時間事件執(zhí)行器運行時,遍歷該鏈表,檢查事件當(dāng)前是否需要執(zhí)行,如需要,則調(diào)用相應(yīng)的時間事件處理器。舉例如下圖所示:

綜上所述,本文關(guān)于 Redis 事件相關(guān)的總結(jié)就到這里了。
歡迎關(guān)注【有理想的菜雞】公眾號,大家一起討論技術(shù),共同成長!
04
相關(guān)閱讀
05
參考資料
《Redis 設(shè)計與實現(xiàn)》黃健宏 著
https://github.com/redis/redis

學(xué)習(xí) | 工作 | 分享
??關(guān)注“有理想的菜雞”
