仔細說一說 I/O 多路複用機制,打一個比方:小曲在 S 城開了一家快遞店,負責同城快送服務。小曲由於資金限制,僱傭了一批快遞員,而後小曲發現資金不夠了,只夠買一輛車送快遞。併發
經營方式一線程
客戶每送來一份快遞,小曲就讓一個快遞員盯着,而後快遞員開車去送快遞。慢慢的小曲就發現了這種經營方式存在下述問題:blog
時間都花在了搶車上了,大部分快遞員都處在閒置狀態,搶到車才能去送快遞。隊列
隨着快遞的增多,快遞員也愈來愈多,小曲發現快遞店裏愈來愈擠,沒辦法僱傭新的快遞員了。事件
快遞員之間的協調很花時間。效率
綜合上述缺點,小曲痛定思痛,提出了經營方式二。cli
經營方式二請求
小曲只僱傭一個快遞員。當客戶送來快遞,小曲按送達地點標註好,依次放在一個地方。最後,讓快遞員依次去取快遞,一次拿一個,再開着車去送快遞,送好了就回來拿下一個快遞。上述兩種經營方式對比,很明顯第二種效率更高。程序
在上述比喻中:im
每一個快遞員→每一個線程
每一個快遞→每一個 Socket(I/O 流)
快遞的送達地點→Socket 的不一樣狀態
客戶送快遞請求→來自客戶端的請求
小曲的經營方式→服務端運行的代碼
一輛車→CPU 的核數
因而有了以下結論:
經營方式一就是傳統的併發模型,每一個 I/O 流(快遞)都有一個新的線程(快遞員)管理。
經營方式二就是 I/O 多路複用。只有單個線程(一個快遞員),經過跟蹤每一個 I/O 流的狀態(每一個快遞的送達地點),來管理多個 I/O 流。
下面類比到真實的 Redis 線程模型,如圖所示:
Redis-client 在操做的時候,會產生具備不一樣事件類型的 Socket。在服務端,有一段 I/O 多路複用程序,將其置入隊列之中。而後,文件事件分派器,依次去隊列中取,轉發到不一樣的事件處理器中。