Redis時間事件分爲以下兩類:
1.定時事件:程序在指定時間執行一次。
2.週期性事件:程序每隔指定時間執行一次。
時間事件的屬性:
1.id:服務器爲時間事件創建的全局唯一ID,ID號從小到大遞增。
2.when:毫秒精度的unix時間戳,記錄時間事件的到達時間。
3.timeProc:時間事件處理器,一個函數。當時間事件到達事,執行此函數。
時間事件的返回值決定了時間事件類型,如返回ae.h/AE_NOMORE,表示事件爲定時事件,到達一次後則刪除;如返回一個非AE_NOMORE的整數,表示事件爲週期性事件,當事件到達之後,服務器會根據返回值更新時間事件的when屬性,並以這種方式一直更新下去。當前Redis版本中只有週期性事件,沒有使用定時事件。
實現:
服務器將所有時間事件都存放在一個無序列表中,每當時間事件執行器執行時,它就遍歷整個鏈表,找到所有已到達的時間事件並調用相應事件處理器。這裏的的無序鏈表,指的是不按when屬性大小排序,其實是按ID排序了,新的時間事件總是插入鏈表的表頭。當前Redis版本中,服務器只使用serverCron一個時間事件,而在benchmark模式下,服務器也只使用2個時間事件,所以使用無序鏈表來保存時間事情,並不影響性能。
serverCron函數:
此函數定期對Redis服務的資源和狀態進行檢查和調整,由redis.c/serverCron執行,工作包括:
1.更新服務器各類統計信息,如時間、內存佔用、數據庫佔用等等。
2.清理數據庫中的過期鍵值對。
3.關閉和清理連接失效的客戶端。
4.嘗試進行AOF和RDB持久化操作。
5.如果當前服務器是主服務器,需要對從服務器進行定期同步。
6.如果出於集羣環境,需要對集羣進行定期同步和連接測試。
事件調度僞代碼:
def aeProcessEvents():
#獲取到達時間離當前時間最接近的時間事件
time_event = aeSearchNearestTimer()
#計算最接近的時間事件距離到達還有多少毫秒
remain_ms = time_event.when - unix_ts_now()
#如果事件已到達,那麼remain_ms 值可能爲負數,置爲0
if remain_ms < 0:
remain_ms = 0
#根據remain_ms值,創建timeval結構
timeval = create_timeval_with_ms(remain_ms)
#阻塞並等待文件事件產生,最大阻塞時間由傳入的timeval結構決定
#如果remaind_ms值爲0,那麼aeApiPoll調用之後馬上返回,不阻塞
aeApiPoll(timeval)
#處理所有已產生的文件事件
processFileEvents()
#處理所有已到達的時間事件
processTimeEvents()