Redis性能解析--Redis為什么那么快?


echo編輯整理,歡迎轉載,轉載請聲明文章來源。歡迎添加echo微信(微信號:t2421499075)交流學習。 百戰不敗,依不自稱常勝,百敗不頹,依能奮力前行。——這才是真正的堪稱強大!!!


Redis的實際被應用都是因為它的性能,在眾多緩存中Redis也是一個比較快的中間件,而且它是單線程操作,沒有過的內存開銷,給程序帶來了更多的擴展空間。

Redis的性能展示

在保證網絡通暢的情況下,相同的CPU和相同的Redis版本,處理不同大小的數據,Redis的吞吐量如下圖所示,該圖來自Redis的官方網站。我們可以在網站中看到。Redis在處理1000字節的數據的時候,都是穩定位置吞吐量在10w,當處理的數據不斷增大的時候,吞吐量才慢慢開始下降。
在這里插入圖片描述
圖片來自redis官網

下圖是提供的QPS測試圖,官方提供的數據是可以達到100000+的QPS(每秒內查詢次數)。
在這里插入圖片描述
圖片來自redis官網

Redis為什么那么快?

  • 純內存KV操作
  • 內部是單程實現的(不需要創建/銷毀線程,避免上下文切換,無並發資源競爭的問題)
  • 異步非阻塞的I/O(多路復用)

存內存KV操作快在哪里?

我們從上面的介紹里面我們看到了Redis是一個純kv的操作。並且Redis絕大部分請求是純粹的內存操作,所以速度非常快。數據存在內存中,類型與存在hashMap中,那么為什么那么快呢?我們可以一起來看一下幾種常用數據結構的對比,和他們的優勢。

數據結構 操作 時間復雜度
List insert O(N)
List select O(1)
Set insert O(1)
Set select O(1)
HashMap insert O(1)
HashMap select O(1)

從上圖我們可以看出,HashMap的優勢就是查找和操作的時間復雜度都是O(1),所以Redis內部采用這種結構能夠從根本上獲得足夠的優勢,當讓,Redis的快速不僅僅是數據結構成就的,還有單程成和異步I/O

Redis為什么使用單線程?

Redis使用單線程就夠了!我們可以看到下圖中官網的描述,Redis的使用瓶頸並不是CPU,它主要受到內存和網絡的限制。例如,使用在一般Linux系統上運行的流水線Redis每秒可以發送一百萬個請求,因此,如果您的應用程序主要使用O(N)或O(log(N))命令,則幾乎不會使用過多的CPU 。
在這里插入圖片描述

從描述中我們可以看到,Redis在使用的時候,使用單線程就已經能夠獲取Redis足夠使用的CPU資源,主要的瓶頸在於內存。但是單線程為什么能夠做到這么快的速度的呢?

Redis使用單線程,相比於多線程快在哪里?

從上面官網的介紹我們看到了,Redis的瓶頸不在線程,不在獲取CPU的資源,所以如果使用多線程就會帶來多余的資源占用。比如上下文切換、資源競爭、鎖的操作。

  • 上下文的切換
    • 上下文其實不難理解,它就是CPU寄存器和程序計數器。主要的作用就是存放沒有被分配到資源的線程,多線程操作的時候,不是每一個線程都能夠直接獲取到CPU資源的,我們之所以能夠看到我們電腦上能夠運行很多的程序,是應為多線程的執行和CPU不斷對多線程的切換。但是總有線程獲取到資源,也總有線程需要等待獲取資源,這個時候,等待獲取資源的線程就需要被掛起,也就是我們的寄存。這個時候我們的上下文就產生了,當我們的上下文再次被喚起,得到資源的時候,就是我們上下文的切換。
  • 競爭資源
    • 競爭資源相對來說比較好理解,CPU對上下文的切換其實就是一種資源分批,但是在切換之前,到底切換到哪一個上下文,就是資源競爭的開始。在我redis中由於是單線程的,所以所有的操作都不會涉及到資源的競爭。
  • 鎖的消耗
    • 對於多線程的情況來講,不能回避的就是鎖的問題。如果說多線程操作出現並發,有可能導致數據不一致,或者操作達不到預期的效果。這個時候我們就需要鎖來解決這些問題。當我們的線程很多的時候,就需要不斷的加鎖,釋放鎖,該操作就會消耗掉我們很多的時間

I/O復用,非阻塞模型

對於I/O阻塞可能有很多人不知道,I/O操作的阻塞到底是怎么引起的,Redis又是怎么解決的呢?

  • I/O操作的阻塞:當用戶線程發出IO請求之后,內核會去查看數據是否就緒,如果沒有就緒就會等待數據就緒,而用戶線程就會處於阻塞狀態,用戶線程交出CPU。當數據就緒之后,內核會將數據拷貝到用戶線程,並返回結果給用戶線程,用戶線程才解除block狀態。
  • Redis采用多路復用:I/O 多路復用其實是在單個線程中通過記錄跟蹤每一個sock(I/O流) 的狀態來管理多個I/O流。select, poll, epoll 都是I/O多路復用的具體的實現。epoll性能比其他幾者要好。redis中的I/O多路復用的所有功能通過包裝常見的select、epoll、evport和kqueue這些I/O多路復用函數庫來實現的。

做一個有底線的博客主


免責聲明!

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



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