1. 程式人生 > >為什麽單線程的Redis這麽快?

為什麽單線程的Redis這麽快?

linu 留言 不必要 set 繼續 tcp服務器 大量 nbsp 構建

一. Redis簡介

Redis是一個開源的內存中的數據結構存儲系統,它可以用作數據庫、緩存和消息中間件。 它支持多種類型的數據結構,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets)等。

二. Redis為什麽這麽快

  1. 完全基於內存,絕大部分請求是純粹的內存操作。 
  2. 數據結構簡單,對數據操作也簡單,Redis中的數據結構是專門進行設計的。 
  3. 采用單線程,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗 CPU,不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因為可能出現死鎖而導致的性能消耗。  
  4. 使用多路I/O復用模型,非阻塞IO。 
  5. 使用底層模型不同,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣,Redis直接自己構建了VM 機制 ,因為一般的系統調用系統函數的話,會浪費一定的時間去移動和請求。

三. 多路I/O復用模型

多路I/O復用模型是利用 select、poll、epoll 可以同時監察多個流的 I/O 事件的能力,在空閑的時候,會把當前線程阻塞掉,當有一個或多個流有 I/O 事件時,就從阻塞態中喚醒,於是程序就會輪詢一遍所有的流(epoll 是只輪詢那些真正發出了事件的流),並且只依次順序的處理就緒的流,這種做法就避免了大量的無用操作。  
  這裏“多路”指的是多個網絡連接,“復用”指的是復用同一個線程。采用多路 I/O 復用技術可以讓單個線程高效的處理多個連接請求(盡量減少網絡 IO 的時間消耗),且 Redis 在內存中操作數據的速度非常快,也就是說內存內的操作不會成為影響Redis性能的瓶頸,主要由以上幾點造就了 Redis 具有很高的吞吐量。

下面舉一個例子,模擬一個tcp服務器處理30個客戶socket。假設你是一個老師,讓30個學生解答一道題目,然後檢查學生做的是否正確,你有下面幾個選擇:

  1. 第一種選擇:按順序逐個檢查,先檢查A,然後是B,之後是C、D。。。這中間如果有一個學生卡主,全班都會被耽誤。這種模式就好比,你用循環挨個處理socket,根本不具有並發能力。
  2. 第二種選擇:你創建30個分身,每個分身檢查一個學生的答案是否正確。 這種類似於為每一個用戶創建一個進程或者線程處理連接。
  3. 第三種選擇,你站在講臺上等,誰解答完誰舉手。這時C、D舉手,表示他們解答問題完畢,你下去依次檢查C、D的答案,然後繼續回到講臺上等。此時E、A又舉手,然後去處理E和A。。。 這種就是IO復用模型,Linux下的select、poll和epoll就是幹這個的。將用戶socket對應的fd註冊進epoll,然後epoll幫你監聽哪些socket上有消息到達,這樣就避免了大量的無用操作。此時的socket應該采用非阻塞模式。這樣,整個過程只在調用select、poll、epoll這些調用的時候才會阻塞,收發客戶消息是不會阻塞的,整個進程或者線程就被充分利用起來,這就是事件驅動,所謂的reactor模式。

四. 單進程單線程好處

  1. 代碼更清晰,處理邏輯更簡單
  2. 不用去考慮各種鎖的問題,不存在加鎖釋放鎖操作,沒有因為可能出現死鎖而導致的性能消耗
  3. 不存在多進程或者多線程導致的切換而消耗CPU

多路I/O復用模型例子參考:https://www.zhihu.com/question/28594409/answer/52835876


下面的是我的公眾號二維碼圖片,歡迎關註,歡迎留言,一起學習,一起進步。

技術分享圖片

為什麽單線程的Redis這麽快?