Redis為什麼這麼快,帶你了解執行緒IO模型!

2021-10-04 18:19:21 字數 1702 閱讀 1561

redis 是個單執行緒程式。

資料都在記憶體中,記憶體操作當然比磁碟操作快。

(1) 使用非阻塞io+io多路復用技術處理。

平常我們自己寫的socket程式都是read和write多少個位元組返回,接收不夠一直阻塞,成為阻塞io,阻塞的時候執行緒幹不了別的事情。套接字提供乙個選項non_blocking,當這個選項開啟時,讀寫方法不會阻塞,而是能讀多少讀多少,能寫多少寫多少。有了非阻塞 io 意味著執行緒在讀寫 io 時可以不必再阻塞了,讀寫可以瞬間完成然後線 程可以繼續幹別的事了。

非阻塞 io 有個問題,那就是執行緒要讀資料,結果讀了一部分就返回了,執行緒如何知道 何時才應該繼續讀。也就是當資料到來時,執行緒如何得到通知。寫也是一樣,如果緩衝區滿 了,寫不完,剩下的資料何時才應該繼續寫,執行緒也應該得到通知。

事件輪詢 api 就是用來解決這個問題的,最簡單的事件輪詢 api 是 select 函式,它是 作業系統提供給使用者程式的 api。輸入是讀寫描述符列表 read_fds & write_fds,輸出是與之 對應的可讀可寫事件。同時還提供了乙個 timeout 引數,如果沒有任何事件到來,那麼就最多 等待 timeout 時間,執行緒處於阻塞狀態。一旦期間有任何事件到來,就可以立即返回。時間過 了之後還是沒有任何事件到來,也會立即返回。拿到事件後,執行緒就可以繼續挨個處理相應 的事件。處理完了繼續過來輪詢。於是執行緒就進入了乙個死迴圈,我們把這個死迴圈稱為事 件迴圈,乙個迴圈為乙個週期。

每個客戶端套接字 socket 都有對應的讀寫檔案描述符。

read_events, write_events = select(read_fds, write_fds, timeout) for event in read_events:

handle_read(event.fd) for event in write_events:

handle_write(event.fd)

handle_others() # 處理其它事情,如定時任務等

因為我們通過 select 系統呼叫同時處理多個通道描述符的讀寫事件,因此我們將這類系 統呼叫稱為多路復用 api。現代作業系統的多路復用 api 已經不再使用 select 系統呼叫,而 改用 epoll(linux)和 kqueue(freebsd & macosx)。

(2) 指令佇列和相應佇列

redis 會將每個客戶端套接字都關聯乙個指令佇列。客戶端的指令通過佇列來排隊進行順序處理,先到先服務。

redis 會將每個客戶端套接字都關聯乙個響應佇列,用來關聯寫事件。

如果隊列為空,那麼意味著連線暫時處於空閒狀態,不需要 去獲取寫事件,也就是可以將當前的客戶端描述符從 write_fds 裡面移出來。等到佇列有資料 了,再將描述符放進去。避免 select 系統呼叫立即返回寫事件,結果發現沒什麼資料可以 寫。出這種情況的執行緒會飆高 cpu。

(3) 定時任務

伺服器處理要響應 io 事件外,還要處理其它事情。比如定時任務就是非常重要的一件 事。如果執行緒阻塞在 select 系統呼叫上,定時任務將無法得到準時排程。那 redis 是如何解 決這個問題的呢?

redis 的定時任務會記錄在乙個稱為最小堆的資料結構中。這個堆中,最快要執行的任 務排在堆的最上方。在每個迴圈週期,redis 都會將最小堆裡面已經到點的任務立即進行處 理。處理完畢後,將最快要執行的任務還需要的時間記錄下來,這個時間就是 select 系統調 用的 timeout 引數。因為 redis 知道未來 timeout 時間內,沒有其它定時任務需要處理,所以 可以安心睡眠 timeout 的時間。

Redis為什麼這麼快?

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

Redis為什麼這麼快?

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

Redis為什麼這麼快?

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