注意:redis 單線程指的是網絡請求模塊使用了一個線程,即一個線程處理全部網絡請求,其餘模塊仍用了多個線程。react
由於CPU不是Redis的瓶頸。Redis的瓶頸最有多是機器內存或者網絡帶寬,既然單線程容易實現,並且CPU不會成爲瓶頸,那就瓜熟蒂落地採用單線程的方案了。關於redis的性能,官方網站也有,普通筆記本輕鬆處理每秒幾十萬的請求redis
一、徹底基於內存,絕大部分請求是純粹的內存操做,很是快速。數據存在內存中,相似於HashMap,HashMap的優點就是查找和操做的時間複雜度都是O(1);服務器
二、數據結構簡單,對數據操做也簡單,Redis中的數據結構是專門進行設計的;網絡
三、採用單線程,避免了沒必要要的上下文切換和競爭條件,也不存在多進程或者多線程致使的切換而消耗 CPU,不用去考慮各類鎖的問題,不存在加鎖釋放鎖操做,沒有由於可能出現死鎖而致使的性能消耗;數據結構
四、使用多路I/O複用模型,非阻塞IO;多線程
五、使用底層模型不一樣,它們之間底層實現方式以及與客戶端之間通訊的應用協議不同,Redis直接本身構建了VM 機制 ,由於通常的系統調用系統函數的話,會浪費必定的時間去移動和請求;併發
3、多路IO複用模型,非阻塞IOsocket
下面舉一個例子,模擬一個tcp服務器處理30個客戶socket。
假設你是一個監考老師,讓30個學生解答一道競賽考題,而後負責驗收學生答卷,你有下面幾個選擇:tcp
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 多路複用函數,而後轉發到相應的事件處理器。