redis是單進程單線程的伺服器,在服務端是使用多路io複用技術實現的,也就是說是基於事件實現的。
redis分為兩種類型的事件,檔案時間和時間事件。
檔案事件:也就是傳統的io操作,基本分為串連,讀取,寫入和關閉。
不同的用戶端發來各種各樣的請求,redis的多工程式會把請求分解為不同的事件,然後將socket和事件一起打包放入隊列中,交給事件分離器處理,事件分離器會把各個事件交給對應的處理器處理。過程如下圖:
io多工程式會監聽不同的socket,只要有事件發生,就會打包放入隊列:
最後交給分離器去消費,可以看到這裡是順序執行的,這就是redis可以做分布式鎖的原因,分布式的程式最終會在redis這裡排隊。
下面看下redis檔案事件的處理器。主要有三類。
應答處理器,主要是對accept函數的封裝,監聽的事件類型是串連,一旦有串連發生,這個處理器就會建立一個通訊端,並且在通訊端上添加新的事件監聽和相應的處理器。
命令要求處理常式,當用戶端調用了write以後,即發送了命令過來,這時伺服器要讀取命令,對應的事件類型是read,是對底層通訊端read函數的封裝,讀取命令,放入緩衝區中,讓後面的命令執行器執行相應的命令。
命令應答處理器,當用戶端執行了read等待伺服器返回結果時會觸發,對應的事件類型是write,是對底層通訊端write函數的封裝,伺服器執行了用戶端的請求,這時就要返回結果。
所以,一次完整的redis請求為:
時間事件:
有兩類,一類是定時事件,只執行一次,另一類是周期事件,執行多次
時間事件的屬性有三個:id,when,handler
服務端會維護一個時間事件的列表,指標是time_events。
然後服務端有一個processTimeEvents函數,會周期性地遍曆這個時間事件列表,一旦需要執行,那麼就會執行該事件的處理函數,執行完以後,如果是周期事件,那麼就會更新事件的when,再次加入到列表裡,否則就扔出列表:
關於時間事件,redis內部有一個很重要的函數就是周期性執行的,serverCron函數,它會:
可以說它就是一個周期性時間事件的處理函數。