為什麼redis是單執行緒的以及為什麼這麼快?

2022-07-03 08:57:12 字數 3535 閱讀 2751

我們先來認真看一下官網的說法。翻譯過來大意如下:

cpu並不是您使用redis的瓶頸,因為通常redis要麼受記憶體限制,要麼受網路限制。例如,使用在一般linux系統上執行的流水線redis每秒可以傳送一百萬個請求,因此,如果您的應用程式主要使用o(n)或o(log(n))命令,則幾乎不會使用過多的cpu 。

但是,為了最大程度地利用cpu,您可以在同一伺服器上啟動多個redis例項,並將它們視為不同的伺服器。在某個時候,單個例項可能還不夠,因此,如果您要使用多個cpu,則可以開始考慮更早地分片的某種方法。

但是,在redis 4.0中,我們開始使redis具有更多執行緒。目前,這僅限於在後台刪除物件,以及阻止通過redis模組實現的命令。對於將來的版本,計畫是使redis越來越執行緒化。

既然redis的瓶頸不是cpu,那麼在單執行緒可以實現的情況下,自然就使用單執行緒了。

我們知道redis是基於記憶體的。那麼我們接下來要了解乙個問題多執行緒cpu和記憶體直接操作差多少?

多執行緒操作就是使用多個cpu模擬多個執行緒,對redis進行操作。這樣會造成乙個巨大的問題,就是cpu的上下文切換問題。cpu的上下文切換的效率比直接在記憶體中進行讀取差的很多。redis使用單個cpu繫結乙個記憶體,針對記憶體的處理就是單執行緒的,這樣避免了上下文的切換,所以非常的快。

一次cpu的切換時間大約是1500ns。從記憶體中讀取1mb的連續資料,耗時大約是250us。如果1mb的資料被多個執行緒讀取了1000次。那麼就是有1000次時間的上下文切換。於是就是1500ns*1000=1500us。結果顯而易見。1500us和250us差的還是很多的。

那麼redis採取單執行緒還避免了很多問題。如果redis使用多執行緒來進行,那麼就要考慮多執行緒帶來的資料安全問題,如果我們在操作redis的list,hash等資料結構的時候。多執行緒就可能存在資料不安全的情況,這是就要加鎖。一旦加鎖就影響了程式的執行速度。

【iops(input/output operations per second)是乙個用於計算機儲存裝置(如硬碟(hdd)、固態硬碟(ssd)或儲存區域網路(san))效能測試的量測方式】

【吞吐量是指對網路、裝置、埠、虛電路或其他設施,單位時間內成功地傳送資料的數量(以位元、位元組、分組等測量)】

記憶體是乙個 iops 非常高的系統,因為我想申請一塊記憶體就申請一塊記憶體,銷毀一塊記憶體我就銷毀一塊記憶體,記憶體的申請和銷毀是很容易的。而且記憶體是可以動態的申請大小的。

磁碟的特性是:ipos很低很低,但吞吐量很高。這就意味著,大量的讀寫操作都必須攢到一起,再提交到磁碟的時候,效能最高。為什麼呢?

如果我有乙個事務組的操作(就是幾個已經分開了的事務請求,比如寫讀寫讀寫,這麼五個操作在一起),在記憶體中,因為iops非常高,我可以乙個乙個的完成,但是如果在磁碟中也有這種請求方式的話,

我第乙個寫操作是這樣完成的:我先在硬碟中定址,大概花費10ms,然後我讀乙個資料可能花費1ms然後我再運算(忽略不計),再寫回硬碟又是10ms ,總共21ms

第二個操作去讀花了10ms, 第三個又是寫花費了21ms ,然後我再讀10ms, 寫21ms ,五個請求總共花費83ms,這還是最理想的情況下,這如果在記憶體中,大概1ms不到。

所以對於磁碟來說,它吞吐量這麼大,那最好的方案肯定是我將n個請求一起放在乙個buff裡,然後一起去提交。

方法就是用非同步:將請求和處理的執行緒不繫結,請求的執行緒將請求放在乙個buff裡,然後等buff快滿了,處理的執行緒再去處理這個buff。然後由這個buff 統一的去寫入磁碟,或者讀磁碟,這樣效率就是最高。

對於慢速裝置,這種處理方式就是最佳的,慢速裝置有磁碟,網路 ,ssd 等等。

我們不能任由作業系統負載均衡,因為我們自己更了解自己的程式,所以我們可以手動地為其分配cpu核,而不會過多地占用cpu」,預設情況下單執行緒在進行系統呼叫的時候會隨機使用cpu核心,為了優化redis,我們可以使用工具為單執行緒繫結固定的cpu核心,減少不必要的效能損耗!

redis作為單程序模型的程式,為了充分利用多核cpu,常常在一台server上會啟動多個例項。而為了減少切換的開銷,有必要為每個例項指定其所執行的cpu。

linux 上 taskset 可以將某個程序繫結到乙個特定的cpu。你比作業系統更了解自己的程式,為了避免排程器愚蠢的排程你的程式,或是為了在多執行緒程式中避免快取失效造成的開銷。

乙個redisserver執行的時候,不是單執行緒的,比如進行rdb備份的時候,就是fork出了乙個子程序來進行實現。

可以通過 ps -ef | grep redis 來檢視到redis的程序pid。

再使用ps -t -p pid 來檢視當前pid下面的執行緒數。

ps命令的「-t」引數表示顯示執行緒(show threads, possibly with spid column.)「spid」欄表示執行緒id,而「cmd」欄則顯示了執行緒名稱。

磁碟資料庫的形式,當我們找資料的時候,先找到索引,通過索引然後關聯到磁碟的資料。如果使用記憶體的方式,可以直接從記憶體中讀取資料。減少了硬碟的io。不受硬碟的讀取速度影響。

redis的每秒查詢次數可以達到10w+。但是隨著連線數的增加,每秒的查詢數會進行減少。通乙個伺服器多個連線數導致。

兩種的方式不同。記憶體是一種半導體的儲存器,是ram。記憶體中的資料是電,一旦斷電記憶體中的資料就會消失。記憶體沒有機械結構。

硬碟是一種機械結構。查詢資料的時候,磁碟要運動到想應的位置。磁頭讀取磁碟裡的資料。

優勢**更清晰,處理邏輯更簡單。

不用去考慮各種鎖的問題,不存在加鎖、釋放鎖操作,沒有因為可能出現死鎖而導致的效能消耗。

不存在「多程序或者多執行緒導致的切換」而消耗cpu。

劣勢無法發揮多核cpu效能,不過可以通過在單機開多個redis例項來完善。

redis 採用網路io多路復用技術,來保證在多連線的時候系統的高吞吐量。

多路-指的是多個socket網路連線,復用-指的是復用乙個執行緒。多路復用主要有三種技術:select,poll,epoll。epoll是最新的、也是目前最好的多路復用技術。

採用多路i/o復用技術:其一,可以讓單個執行緒高效處理多個連線請求(儘量減少網路io的時間消耗)。其二,redis在記憶體中運算元據的速度非常快(記憶體裡的操作不會成為這裡的效能瓶頸)。主要以上兩點造就了redis具有很高的吞吐量。

採用多路 i/o 復用技術可以讓單個執行緒高效的處理多個連線請求。

1、redis是純記憶體資料庫,一般都是簡單的訪問操作,執行緒占用的時間很多,時間的花費主要集中在io上,所以讀取速度快。

2、redis使用的是非阻塞io、io多路復用,使用了單執行緒來輪詢描述符,將資料庫的開、關、讀、寫都轉換成了事件,減少了執行緒切換時上下文的切換和競爭。

3、redis採用了單執行緒的模型,保證了每個操作的原子性,也減少了執行緒的上下文切換和競爭。

4、redis避免了多執行緒的鎖的消耗。

5、redis採用自己實現的事件分離器,效率比較高,內部採用非阻塞的執行方式,吞吐能力比較大。

Redis為什麼是單執行緒

經過多方資料收集 總結 思考,結論如下 準確地來說,該問題是 為什麼redis採用單程序單執行緒模型 我們從兩個層次去理解 第乙個層次 我們多執行緒的使用情景是io密集型,目的是為了充分利用cpu資源。也就是說當乙個執行緒io等待的時候,另乙個執行緒可以進行執行,達到充分利用cpu資源的效果,不要讓...

Redis為什麼是單執行緒的

因為redis是基於記憶體的操作,cpu不是redis的瓶頸,redis的瓶頸最有可能是機器記憶體的大小或者網路頻寬。既然單執行緒容易實現,而且cpu不會成為瓶頸,那就順理成章地採用單執行緒的方案了。二 詳細原因 1 不需要各種鎖的效能消耗 redis的資料結構並不全是簡單的key value,還有...

為什麼redis是單執行緒的

redis是單執行緒的原因 1 單執行緒不需要各種鎖的效能消耗 2 單執行緒多程序集群方案 3 採用單執行緒避免了不必要的上下文切換和競爭條件,也不存在多程序或者多執行緒導致的切換而消耗cpu。簡單分析 推薦教程 redis教程 redis是基於記憶體的操作,cpu不是redis的瓶頸,redis的...