redis如此之快,整體來說原因如下
-
絕大部分請求是純粹的內存操作(非常快速)
-
采用單線程,避免了不必要的上下文切換和競爭條件
-
非阻塞IO 內部實現采用epoll,采用了epoll+自己實現的簡單的事件框架。epoll中的讀、寫、關閉、連接都轉化成了事件,然后利用epoll的多路復用特性,絕不在io上浪費一點時
這3個條件不是相互獨立的,特別是第一條,如果請求都是耗時的,采用單線程吞吐量及性能可想而知了。應該說redis為特殊的場景選擇了合適的技術方案。
對BIO、NIO和AIO的概念解析
所有的系統IO都分為兩個階段:等待就緒和操作。例如:讀函數分為等待系統可讀和真正的讀;同理,寫函數分為等待網卡可寫和真正的寫。
- BIO里用戶最關心"我要讀";我要一直等在這處理處理時間;
- NIO里用戶最關心"我可以讀了";我不在這等了,如果有事件發生,你就通知我,我再來處理;
- AIO里用戶最關心"讀完了";你幫我處理吧,處理完了通知我。
BIO
Java BIO : 同步並阻塞,服務器實現模式為一個連接一個線程,即客戶端有連接請求時服務器端就需要啟動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷,當然可以通過線程池機制改善。
每一個線程守着一個IO通道,當沒有IO時這個線程就阻塞着,一旦有IO事件發生,這個線程就開始工作
缺點
- 嚴重依賴線程:
- 線程的創建和銷毀成本很高;
- 線程本身占用較大內存;
- 線程切換成本很高;
- 容易造成鋸齒狀的系統負載;

NIO
1.同步非阻塞,服務器實現模式為一個請求一個線程,即客戶端發送的連接請求都會注冊到多路復用器上,多路復用器輪詢到連接有I/O請求時才啟動一個線程進行處理。socket主要的讀、寫、注冊和接受函數,在等待就緒階段都是非阻塞的,真正的IO操作是同步阻塞的。
將每個連接(IO通道)都注冊到Selector多路復用器上,告訴復用器我已經連接了,如果有IO事件發生,你就通知我。Selector就不斷地調用select函數,去訪問每一個通道看那個通道有IO事件發生,如果發生了就通知,內核開啟一個對應事件的線程去工作
2. 異步非阻塞,服務器實現模式為一個有效請求一個線程,客戶端的I/O請求都是由OS先完成了再通知服務器應用去啟動線程進行處理。當進行讀寫操作時,只須直接調用API的read或write方法即可。這兩種方法均為異步的,對於讀操作而言,當有流可讀取時,操作系統會將可讀的流傳入read方法的緩沖區,並通知應用程序;對於寫操作而言,當操作系統將write方法傳遞的流寫入完畢時,操作系統主動通知應用程序。 即可以理解為,read/write方法都是異步的,完成后會主動調用回調函數。
來源:SEO技術
