Redis單線程為什么執行效率這么高?


 

 

一、Redis為什么是單線程

注意:redis 單線程指的是網絡請求模塊使用了一個線程,即一個線程處理所有網絡請求,其他模塊仍用了多個線程。

因為CPU不是Redis的瓶頸。Redis的瓶頸最有可能是機器內存或者網絡帶寬,既然單線程容易實現,而且CPU不會成為瓶頸,那就順理成章地采用單線程的方案了。關於redis的性能,官方網站也有,普通筆記本輕松處理每秒幾十萬的請求。

二、Redis為什么這么快

1、完全基於內存,絕大部分請求是純粹的內存操作,非常快速。數據存在內存中,類似於HashMap,HashMap的優勢就是查找和操作的時間復雜度都是O(1);

2、數據結構簡單,對數據操作也簡單,Redis中的數據結構是專門進行設計的;

3、采用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗 CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因為可能出現死鎖而導致的性能消耗;

4、使用多路I/O復用模型,非阻塞IO;

5、使用底層模型不同,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣,Redis直接自己構建了VM 機制 ,因為一般的系統調用系統函數的話,會浪費一定的時間去移動和請求;

三、多路I/O復用模型,非阻塞IO

下面舉一個例子,模擬一個tcp服務器處理30個客戶socket。

假設你是一個監考老師,讓30個學生解答一道競賽考題,然后負責驗收學生答卷,你有下面幾個選擇:

1. 第一種選擇:按順序逐個驗收,先驗收A,然后是B,之后是C、D。。。這中間如果有一個學生卡住,全班都會被耽誤。

這種模式就好比,你用循環挨個處理socket,根本不具有並發能力。

2. 第二種選擇:你創建30個分身,每個分身檢查一個學生的答案是否正確。這種類似於為每一個用戶創建一個進程或者線程處理連接。

3. 第三種選擇,你站在講台上等,誰解答完誰舉手。這時C、D舉手,表示他們解答問題完畢,你下去依次檢查C、D的答案,然后繼續回到講台上等。此時E、A又舉手,然后去處理E和A。。。

這種就是IO復用模型,Linux下的select、poll和epoll就是干這個的。將用戶socket對應的fd注冊進epoll,然后epoll幫你監聽哪些socket上有消息到達,這樣就避免了大量的無用操作。此時的socket應該采用非阻塞模式。

這樣,整個過程只在調用select、poll、epoll這些調用的時候才會阻塞,收發客戶消息是不會阻塞的,整個進程或者線程就被充分利用起來,這就是事件驅動,所謂的reactor模式。

針對上面的舉例在Redis中表現為

有30個redis客戶端(考生)與redis服務器的網絡連接模塊(監考老師)保持TCP連接,客戶端會不定時的發送請求給服務器,當有一個redis客戶端發起請求,會觸發unix系統像epoll這樣的系統調用,Redis的I/O 多路復用模塊封裝了底層的epoll這樣的 I/O 多路復用函數,然后轉發到相應的事件處理器。

最后多路I/O復用模型圖

面試官:Redis單線程為什么執行效率這么高?

 

文件事件處理器使用 I/O 多路復用模塊同時監聽多個 FD(文件描述符),當 accept、read、write 和 close 文件事件產生時,文件事件處理器就會回調 FD 綁定的事件處理器。

雖然整個文件事件處理器是在單線程上運行的,但是通過 I/O 多路復用模塊的引入,實現了同時對多個 FD 讀寫的監控,提高了網絡通信模型的性能,同時也可以保證整個 Redis 服務實現的簡單。

 

Redis除了內存操作之外,其他就不要過度解讀了,據說Redis6要加多線程了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM