Redis 單線程模型介紹


1. 理解單線程模型

 

 

  1. redis 會將每個客戶端都關聯一個指令隊列。客戶端的指令通過隊列來按順序處理,先到先服務。
  2. 在一個客戶端的指令隊列中的指令是順序執行的,但是多個指令隊列中的指令是無法保證順序的,例如執行完 client-0 的隊列中的 command-0 后,接下去是執行哪個隊列中的第一個指令是無法確定的,但是肯定不會同時執行兩個指令。
  3. redis 同樣也會為每個客戶端關聯一個響應隊列,通過響應隊列來順序地將指令的返回結果回復給客戶端。
  4. 同樣,一個響應隊列中的消息可以順序的回復給客戶端,多個響應隊列之間是無法保證順序的。
  5. 所有的客戶端的隊列中的指令或者響應,redis 每次都只能處理一個,同一時間絕對不會處理超過一個指令或者響應。

 

2. 為什么redis使用單線程模型還能保證高性能?

(1) 純內存訪問

redis 將所有數據放在內存中,內存的響應時長大約為 100 納秒,這是 redis 的 QPS 過萬的重要基礎。

(2) 非阻塞式IO

  • 什么是阻塞式 IO

當我們調用 Scoket 的讀寫方法,默認它們是阻塞的。

read() 方法要傳遞進去一個參數 n,表示讀取這么多字節后再返回,如果沒有讀夠 n 字節線程就會阻塞,直到新的數據到來或者連接關閉了, read 方法才可以返回,線程才能繼續處理。

write() 方法會首先把數據寫到系統內核為 Scoket 分配的寫緩沖區中,當寫緩存區滿溢,即寫緩存區中的數據還沒有寫入到磁盤,就有新的數據要寫道寫緩存區時,write() 方法就會阻塞,直到寫緩存區中有空閑空間。

  • 什么是非阻塞式 IO

非阻塞 IO 在 Scoket 對象上提供了一個選項Non_Blocking ,當這個選項打開時,讀寫方法不會阻塞,而是能讀多少讀多少,能寫多少寫多少。

能讀多少取決於內核為 Scoket 分配的讀緩沖區的大小,能寫多少取決於內核為 Scoket 分配的寫緩沖區的剩余空間大小。讀方法和寫方法都會通過返回值來告知程序實際讀寫了多少字節數據。

有了非阻塞 IO 意味着線程在讀寫 IO 時可以不必再阻塞了,讀寫可以瞬間完成然后線程可以繼續干別的事了。

(3) IO多路復用

非阻塞 IO 有個問題,那就是單個線程要處理多個讀寫請求,處理某個客戶端的的讀數據的請求,結果讀了一部分就返回了,線程如何知道什么時候才應該繼續讀數據。處理寫請求的時候,如果緩沖區滿了,寫不完,剩下的數據何時才應該繼續寫?在什么時候處理什么請求?redis 單線程處理多個IO請求時就用到了IO多路復用技術。

簡單的理解下 IO 多路復用技術,假設每個客戶端的 IO 請求是一條電路,redis 是一個開關,如下圖所示:

 

 

在上圖中,redis 需要處理 3 個 IO 請求,同時把 3 個請求的結果返回給客戶端,所以總共需要處理 6 個 IO 事件,由於 redis 是單線程模型,同一時間只能處理一個 IO 事件,於是 redis 需要在合適的時間暫停對某個 IO 事件的處理,轉而去處理另一個 IO 事件,這樣 redis 就好比一個開關,當開關撥到哪個 IO 事件這個電路上,就處理哪個 IO 事件,其他 IO 事件就暫停處理了。這就是IO多路復用技術。

以上是大致的理解下 IO 多路復用技術,在系統底層,IO 多路復用有 3 種實現機制:

  • select
  • poll
  • epoll

這些實現機制的底層我不清楚,看過一些博客(細節也沒看懂),總結一下就是:

epoll 是目前最新的也是最先進的 IO 多路復用的實現解決了select 和 poll 的很多問題。而 redis 就是使用的基於 epoll 的 IO 多路復用技術。

對這 3 種實現機制感興趣的話,可以去看看大神的博客,本人在這里就不再胡說了。

 

(4) 單線程避免了線程切換和競態產生的消耗。

單線程能帶來幾個好處:

  • 第一,單線程可以簡化數據結構和算法的實現。並發數據結構實現不但困難而且開發測試比較麻
  • 第二,單線程避免了線程切換和競態產生的消耗,對於服務端開發來說,鎖和線程切換通常是性能殺手。
  • 單線程的問題:對於每個命令的執行時間是有要求的。如果 某個命令執行過長,會造成其他命令的阻塞,所以 redis 適用於那些需要快速執行的場景。

 

原文: https://cloud.tencent.com/developer/article/1403767

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM