線程模型
redis 內部使用文件事件處理器 file event handler
,這個文件事件處理器是單線程的,所以 redis 才叫做單線程的模型。
它采用 IO 多路復用機制同時監聽多個 socket,根據 socket 上的事件來選擇對應的事件處理器進行處理。
IO 多路復用相關請移步到這篇文章-> IO多路復用模型
文件事件處理器的結構包含 4 個部分:
- 多個 socket
- IO 多路復用程序
- 文件事件分派器
- 事件處理器(連接應答處理器、命令請求處理器、命令回復處理器)
多個 socket 可能會並發產生不同的操作,每個操作對應不同的文件事件,但是 IO 多路復用程序會監聽多個 socket,會將 socket 產生的事件放入隊列中排隊,事件分派器每次從隊列中取出一個事件,把該事件交給對應的事件處理器進行處理。
來看客戶端與 redis 的一次通信過程:
客戶端 socket01 向 redis 的 server socket 請求建立連接,此時 server socket 會產生一個 AE_READABLE
事件,IO 多路復用程序監聽到 server socket 產生的事件后,將該事件壓入隊列中。文件事件分派器從隊列中獲取該事件,交給連接應答處理器。連接應答處理器會創建一個能與客戶端通信的 socket01,並將該 socket01 的 AE_READABLE
事件與命令請求處理器關聯。
假設此時客戶端發送了一個 set key value
請求,此時 redis 中的 socket01 會產生 AE_READABLE
事件,IO 多路復用程序將事件壓入隊列,此時事件分派器從隊列中獲取到該事件,由於前面 socket01 的 AE_READABLE
事件已經與命令請求處理器關聯,因此事件分派器將事件交給命令請求處理器來處理。命令請求處理器讀取 socket01 的 key value
並在自己內存中完成 key value
的設置。操作完成后,它會將 socket01 的 AE_WRITABLE
事件與命令回復處理器關聯。
如果此時客戶端准備好接收返回結果了,那么 redis 中的 socket01 會產生一個 AE_WRITABLE
事件,同樣壓入隊列中,事件分派器找到相關聯的命令回復處理器,由命令回復處理器對 socket01 輸入本次操作的一個結果,比如 ok
,之后解除 socket01 的 AE_WRITABLE
事件與命令回復處理器的關聯。
這樣便完成了一次通信。
為啥 redis 單線程模型也能效率這么高?
- 純內存操作
- 核心是基於非阻塞的 IO 多路復用機制
- 單線程反而避免了多線程的頻繁上下文切換問題