Redis系列 六 為什麼這麼快?

2022-02-18 21:38:47 字數 3187 閱讀 7636

redis作為乙個基於key-value的nosql資料庫,最顯著的特點訪問速度非常快,官方說可以達到10w ops,但是redis為何這麼快?

1、開發語言

redis使用c語言進行編寫的,而unix系統也是c語言實現,所以c語言是非常貼近作業系統的語言

2、基於記憶體讀寫

基於記憶體讀寫是redis速度快的主要原因,不進行資料同步的情況下,不從磁碟讀取資料,沒有io。記憶體響應時間大約100ns

3、單執行緒

1).單執行緒避免了執行緒上下文切換以及同步加鎖、解鎖帶來的消耗。

2).單執行緒簡化演算法的實現

3).單執行緒也帶來乙個問題,阻塞,對於乙個長命令來說,會阻塞很多命令的執行響應

這裡的單執行緒,不包含fork()產生的子程序。除了redis之外,node.js、nginx都是單執行緒,都屬於高效能的元件框架

4、多路i/o復用模型

由於redis是單執行緒的,所有的操作都是序列執行,但是由於讀寫操作等待使用者輸入或輸出都是阻塞的,所以 i/o 操作在一般情況下往往不能直

接返回,

這會導致某一檔案的 i/o 阻塞導致整個程序無法對其它客戶提供服務,而 i/o 多路復用就是為了解決這個問題而出現的。

redis的i/o模型基於epoll實現,也提供select和kqueue的實現,預設epoll

epoll相對於其他多路復用技術,具有的優點:

1. epoll沒有最大併發連線的限制,上限是最大可以開啟檔案的數目,這個數字一般遠大於 2048

2. 效率提公升,epoll最大的優點就在於它只管你「活躍」的連線,而跟連線總數無關,因此在實際的網路環境中, epoll的效率就會遠遠高於

select和poll

3. 記憶體拷貝,epoll在這點上使用了「共享記憶體 」,這個記憶體拷貝也省略了。

epoll與select/poll的區別:

i/o多路復用:通過一種機制,可以監視多個描述符(file descriptor,簡稱fd),一旦某個描述符就緒,能夠通知程式進行相應的操作。

1、select:

本質是採用32個整數的32位,即32*32 = 1024來標識,fd值為1-1024。當fd的值超過1024限制時,就必須修改fd_setsize的大小。這個時候就

可以標識32*max值範圍的fd。

2、poll:

poll與select不同,通過乙個pollfd陣列向核心傳遞需要關注的事件,故沒有描述符個數的限制,pollfd中的events欄位和revents分別用於

標示關注的事件和發生的事件,

故pollfd陣列只需要被初始化一次。

3、epoll:

是poll的一種優化,返回後不需要對所有的fd進行遍歷,在核心中維持了fd的列表。select和poll是將這個核心列表維持在使用者態,然後傳遞

到核心中。

與poll/select不同,epoll不再是乙個單獨的系統呼叫,而是由epoll_create/epoll_ctl/epoll_wait三個系統呼叫組成,後面將會看到

這樣做的好處。epoll在2.6以後的核心才支援。

select/poll的幾大缺點:

1、每次呼叫select/poll,都需要把fd集合從使用者態拷貝到核心態,這個開銷在fd很多時會很大

2、同時每次呼叫select/poll都需要在核心遍歷傳遞進來的所有fd,這個開銷在fd很多時也很大

3、針對select支援的檔案描述符數量太小了,預設是1024

4.select返回的是含有整個控制代碼的陣列,應用程式需要遍歷整個陣列才能發現哪些控制代碼發生了事件;

5.select的觸發方式是水平觸發,應用程式如果沒有完成對乙個已經就緒的檔案描述符進行io操作,那麼之後每次select呼叫還是會將這些文

件描述符通知程序。

相比select模型,poll使用鍊錶儲存檔案描述符,因此沒有了監視檔案數量的限制,但其他三個缺點依然存在。

epoll io多路復用模型實現機制:

由於epoll的實現機制與select/poll機制完全不同,上面所說的 select的缺點在epoll上不復存在。

epoll沒有這個限制,它所支援的fd上限是最大可以開啟檔案的數目,這個數字一般遠大於2048,舉個例子,在1gb記憶體的機器上大約是10萬左右

設想一下如下場景:有100萬個客戶端同時與乙個伺服器程序保持著tcp連線。而每一時刻,通常只有幾百上千個tcp連線是活躍的(事實上大部

分場景都是這種情況)。

如何實現這樣的高併發?

在select/poll時代,伺服器程序每次都把這100萬個連線告訴作業系統(從使用者態複製控制代碼資料結構到核心態),讓作業系統核心去查詢這些套

接字上是否有事件發生,

輪詢完後,再將控制代碼資料複製到使用者態,讓伺服器應用程式輪詢處理已發生的網路事件,這一過程資源消耗較大,因此,

select/poll一般只能處理幾千的併發連線。

如果沒有i/o事件產生,我們的程式就會阻塞在select處。但是依然有個問題,我們從select那裡僅僅知道了,有i/o事件發生了,但卻並不知

道是那幾個流(

可能有乙個,多個,甚至全部),

我們只能無差別輪詢所有流,找出能讀出資料,或者寫入資料的流,對他們進行操作。

但是使用

select,我們有o(n)的無差別輪詢複雜度,

同時處理的流越多,每一次無差別輪詢時間就越長

epoll的設計和實現與select完全不同。epoll通過在linux核心中申請乙個簡易的檔案系統(檔案系統一般用什麼資料結構實現?b+樹)。把原先的

select/poll呼叫分成了3個部分:

1)呼叫epoll_create()建立乙個epoll物件(在epoll檔案系統中為這個控制代碼物件分配資源)

2)呼叫epoll_ctl向epoll物件中新增這100萬個連線的套接字

3)呼叫epoll_wait收集發生的事件的連線

如此一來,要實現上面說是的場景,只需要在程序啟動時建立乙個epoll物件,然後在需要的時候向這個epoll物件中新增或者刪除連線。同時,

epoll_wait的效率也非常高,

因為呼叫epoll_wait時,並沒有一股腦的向作業系統複製這100萬個連線的控制代碼資料,核心也不需要去遍歷全部的連線。

Redis為什麼這麼快?

今天我在乙個技術群裡提出乙個問題 redis為什麼這麼快,redis的那些特性能夠支援了它的高併發?之前的我,也只是知道redis是記憶體資料庫,所以讀取速度快 io使用的是多路復用,使用乙個執行緒來輪詢描述符,減少了執行緒上下文的切換,將資料庫的開 關 讀 寫都轉化成了時間,所以io時也有加速。雖...

Redis為什麼這麼快?

1 完全基於記憶體,絕大部分請求是純粹的記憶體操作,非常快速。資料存在記憶體中,類似於hashmap,hashmap的優勢就是查詢和操作的時間複雜度都是o 1 2 資料結構簡單,對資料操作也簡單,redis中的資料結構是專門進行設計的 3 採用單執行緒,避免了不必要的上下文切換和競爭條件,也不存在多...

Redis為什麼這麼快?

目錄 一 redis為什麼這麼快?二 redis為什麼是單執行緒的?redis採用的是基於記憶體的採用的是單程序單執行緒模型的 kv 資料庫,由c語言編寫,官方提供的資料是可以達到100000 的qps 每秒內查詢次數 以下幾點造就了redis非常快的特點 採用單執行緒避免了不必要的上下文切換和競爭...