單執行緒的Redis為什麼這麼快,為什麼響應延遲這麼低?
- 2019 年 12 月 2 日
- 筆記
分析:這個問題其實是對redis內部機制的一個考察。其實根據部落客的面試經驗,很多人其實都不知道redis是單執行緒工作模型。所以,這個問題還是應該要複習一下的。 回答:主要是以下三點 (一)純記憶體操作 (二)單執行緒操作,避免了頻繁的上下文切換 (三)採用了非阻塞I/O多路復用機制
題外話:我們現在要仔細的說一說I/O多路復用機制,因為這個說法實在是太通俗了,通俗到一般人都不懂是什麼意思。部落客打一個比方:小曲在S城開了一家快遞店,負責同城快送服務。小曲因為資金限制,僱傭了一批快遞員,然後小曲發現資金不夠了,只夠買一輛車送快遞。 經營方式一 客戶每送來一份快遞,小曲就讓一個快遞員盯著,然後快遞員開車去送快遞。慢慢的小曲就發現了這種經營方式存在下述問題
- 幾十個快遞員基本上時間都花在了搶車上了,大部分快遞員都處在閑置狀態,誰搶到了車,誰就能去送快遞
- 隨著快遞的增多,快遞員也越來越多,小曲發現快遞店裡越來越擠,沒辦法僱傭新的快遞員了
- 快遞員之間的協調很花時間
綜合上述缺點,小曲痛定思痛,提出了下面的經營方式 經營方式二 小曲只僱傭一個快遞員。然後呢,客戶送來的快遞,小曲按送達地點標註好,然後依次放在一個地方。最後,那個快遞員依次的去取快遞,一次拿一個,然後開著車去送快遞,送好了就回來拿下一個快遞。
對比 上述兩種經營方式對比,是不是明顯覺得第二種,效率更高,更好呢。在上述比喻中:
- 每個快遞員——————>每個執行緒
- 每個快遞——————–>每個socket(I/O流)
- 快遞的送達地點————–>socket的不同狀態
- 客戶送快遞請求————–>來自客戶端的請求
- 小曲的經營方式————–>服務端運行的程式碼
- 一輛車———————->CPU的核數
於是我們有如下結論 1、經營方式一就是傳統的並發模型,每個I/O流(快遞)都有一個新的執行緒(快遞員)管理。 2、經營方式二就是I/O多路復用。只有單個執行緒(一個快遞員),通過跟蹤每個I/O流的狀態(每個快遞的送達地點),來管理多個I/O流。
下面類比到真實的redis執行緒模型,如圖所示

參照上圖,簡單來說,就是。我們的redis-client在操作的時候,會產生具有不同事件類型的socket。在服務端,有一段I/0多路復用程式,將其置入隊列之中。然後,文件事件分派器,依次去隊列中取,轉發到不同的事件處理器中。 需要說明的是,這個I/O多路復用機制,redis還提供了select、epoll、evport、kqueue等多路復用函數庫,大家可以自行去了解。