redis為什麼那麼快?結論有三點,大家都知道,這裡主要是分析。 首先第一點 redis是記憶體訪問的,所以快 當然這個大家都知道,所以不是重點 io密集型和cpu密集型 一般我們把任務分為io密集型和cpu密集型 io密集型 IO密集型指的是系統的CPU性能相對硬碟、記憶體要好很多,此時,系統運作,大 ...
redis為什麼那麼快?結論有三點,大家都知道,這裡主要是分析。
首先第一點
redis是記憶體訪問的,所以快
當然這個大家都知道,所以不是重點
io密集型和cpu密集型
一般我們把任務分為io密集型和cpu密集型
io密集型
- IO密集型指的是系統的CPU性能相對硬碟、記憶體要好很多,此時,系統運作,大部分的狀況是CPU在等I/O (硬碟/記憶體) 的讀/寫操作,此時CPU Loading並不高。
- 對於io密集型的任務,它的主要時間都在磁碟io上,而io本身在發出中斷告知cpu後,cpu只需要短暫的處理一下,之後就由DMA(詳見附錄)負責數據傳輸,整個過程對cpu的利用率很低。因此我們需要開更多的線程去充分利用cpu。即一般線程數 = cpu核心數 * 2,如資料庫連接池
cpu密集型
- CPU密集型也叫計算密集型,指的是系統的硬碟、記憶體性能相對CPU要好很多,此時,系統運作大部分的狀況是CPU Loading 100%,CPU要讀/寫I/O(硬碟/記憶體),I/O在很短的時間就可以完成,而CPU還有許多運算要處理,CPU Loading很高。
- 對於cpu密集型的任務,它對cpu的利用率很高,所以不需要開更多的線程去提高cpu利用率。假如增加線程,只會引起線程的頻繁切換導致本來就不夠用的cpu更加不夠用。所以一般是線程數 = cpu核心數 + 1
redis的瓶頸在哪裡
redis基本都在進行記憶體io,那它的瓶頸在io上嗎?
redis在網路io上使用epoll實現了一個io多路復用的reactor模型,epoll是非阻塞io,所以避免了cpu阻塞在io上,所以它不是io密集型,瓶頸不在於等待io導致cpu利用率不高,不需要多個線程來屏蔽等待io執行完成的時間。當然redis的io利用率很高,但是io利用率高並不代表它是io密集型,因為它瓶頸不在等待io上。
所以第二點
redis在網路io上使用epoll實現了一個io多路復用的reactor模型使得cpu利用率更高,浪費在io上的時間更少
redis並不需要多線程來提高cpu利用率減少io等待時間,並且單線程架構也比較容易實現,所以順理成章就採用了單線程架構。
關於epoll可以看我的這篇文章:https://www.cnblogs.com/fatmanhappycode/p/12362423.html
第三點
由於採用了單線程架構,避免了線程線程切換產生的消耗
因為一次CPU上下文的切換大概在 1500ns 左右。
從記憶體中讀取 1MB 的連續數據,耗時大約為 250us,假設1MB的數據由多個線程讀取了1000次,那麼就有1000次時間上下文的切換,
那麼就有1500ns * 1000 = 1500us ,我單線程的讀完1MB數據才250us ,你光時間上下文的切換就用了1500us了,我還不算你每次讀一點數據 的時間
那麼redis是cpu密集型嗎?答案是否定的。
redis也不是cpu密集型。大多數情況下redis機器上的cpu是很夠用的。
redis的瓶頸在於記憶體大小和網路帶寬。
如果想要更充分的利用多核cpu,可以採用多個redis實例的方法,同時為了減少線程爭用,可以將實例和cpu綁定的方法。
但是如果做了CPU綁定,在rdb和aof時子進程會與父進程共用使用一個CPU。子進程重寫時對單核CPU使用率通常在90%以上,父進程與子進程將產生激烈CPU競爭,極大影響Redis穩定性。(解決方法不清楚,也許多綁定一個CPU會好點?)
附錄
DMA
DMA 傳輸將數據從一個地址空間複製到另外一個地址空間。當CPU 初始化這個傳輸動作,傳輸動作本身是由 DMA 控制器來實行和完成。
典型的例子就是移動一個外部記憶體的區塊到晶元內部更快的記憶體區。例如記憶體移到磁碟。
最後慣例附一圖:
參考資料:
https://www.php.cn/redis/422123.html
https://blog.csdn.net/youanyyou/article/details/78990156