一、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 語言實現,語言更接近作業系統,執行速度相對會更快。
- 單執行緒反而避免了多執行緒的頻繁上下文切換問題,預防了多執行緒可能產生的競爭問題。
參考:中華石衫老師的億級流量電商詳情頁快取架構設計教程
hi~我是Mirror,一個為了自由安逸的未來而不斷前進的的程式設計師。
如果你覺得文章對你有一點點幫助,一個小小贊,便是對我的認可,如果有不足之處,也歡迎各位指正。