一、redis 的線程模型
redis 內部使用文件事件處理器 file event handler,它是單線程的,所以redis才叫做單線程模型。它采用IO多路復用機制同時監聽多個 socket,將產生事件的 socket 壓入內存隊列中,事件分派器根據 socket 上的事件類型來選擇對應的事件處理器進行處理。
文件事件處理器的結構:
- 多個 socket
- IO 多路復用程序
- 文件事件分派器
- 事件處理器(連接應答處理器、命令請求處理器、命令回復處理器)
線程模型
多個 socket 可能會並發產生不同的操作,每個操作對應不同的文件事件,但是 IO多路復用程序會監聽多個 socket,會將產生事件的 socket 放入隊列中排隊,事件分派器每次從隊列中取出一個 socket,根據 socket 的事件類型交給對應的事件處理器進行處理。
二、一次客戶端與redis的完整通信過程
建立連接
-
首先,redis 服務端進程初始化的時候,會將 server socket 的 AE_READABLE 事件與連接應答處理器關聯。
-
客戶端 socket01 向 redis 進程的 server socket 請求建立連接,此時 server socket 會產生一個 AE_READABLE 事件,IO 多路復用程序監聽到 server socket 產生的事件后,將該 socket 壓入隊列中。
-
文件事件分派器從隊列中獲取 socket,交給連接應答處理器。
-
連接應答處理器會創建一個能與客戶端通信的 socket01,並將該 socket01 的 AE_READABLE 事件與命令請求處理器關聯。
執行一個set請求
-
客戶端發送了一個 set key value 請求,此時 redis 中的 socket01 會產生 AE_READABLE 事件,IO 多路復用程序將 socket01 壓入隊列,
-
此時事件分派器從隊列中獲取到 socket01 產生的 AE_READABLE 事件,由於前面 socket01 的 AE_READABLE 事件已經與命令請求處理器關聯,
-
因此事件分派器將事件交給命令請求處理器來處理。命令請求處理器讀取 socket01 的 key value 並在自己內存中完成 key value 的設置。
-
操作完成后,它會將 socket01 的 AE_WRITABLE 事件與命令回復處理器關聯。
-
如果此時客戶端准備好接收返回結果了,那么 redis 中的 socket01 會產生一個 AE_WRITABLE 事件,同樣壓入隊列中,
-
事件分派器找到相關聯的命令回復處理器,由命令回復處理器對 socket01 輸入本次操作的一個結果,比如 ok,之后解除 socket01 的 AE_WRITABLE 事件與命令回復處理器的關聯。
三、redis為什么效率這么高?
- 純內存操作。
- 核心是基於非阻塞的 IO 多路復用機制。
- C 語言實現,語言更接近操作系統,執行速度相對會更快。
- 單線程反而避免了多線程的頻繁上下文切換問題,預防了多線程可能產生的競爭問題。
參考:中華石衫老師的億級流量電商詳情頁緩存架構設計教程