linux redis客户端_为什么单线程Redis能那么快?
Redis 為什么用單線程?
多線程的開銷
對于一個多線程的系統來說,在有合理的資源分配的情況下,可以增加系統中處理請求操作的資源實體,進而提升系統能夠同時處理的請求數,即吞吐率。
線程數與系統吞吐率- 管理共享資源的開銷
采用多線程開發一般會引入同步原語來保護共享資源的并發訪問,這也會降低系統代碼的易調試性和可維護性。為了避免這些問題,Redis 直接采用了單線程模式。
單線程 Redis 為什么那么快?
- Redis 的大部分操作在內存上完成
- 采用了高效的數據結構
- 采用了多路復用機制使其在網絡 IO 操作中能并發處理大量的客戶端請求,實現高吞吐率
基本 IO 模型與阻塞點
下圖顯示了這一過程,其中,bind/listen、accept、recv、parse 和 send 屬于網絡 IO 處理,而 get 屬于鍵值數據操作。既然 Redis 是單線程,那么,最基本的一種實現是在一個線程中依次執行上面說的這些操作。
Redis基本IO模型在這里的網絡 IO 操作中,有潛在的阻塞點,分別是 accept() 和 recv()。當 Redis 監聽到一個客戶端有連接請求,但一直未能成功建立起連接時,會阻塞在 accept() 函數這里,導致其他客戶端無法和 Redis 建立連接。類似的,當 Redis 通過 recv() 從一個客戶端讀取數據時,如果數據一直沒有到達,Redis 也會一直阻塞在 recv()。
這就導致 Redis 整個線程阻塞,無法處理其他客戶端請求,效率很低。不過,幸運的是,socket 網絡模型本身支持非阻塞模式。
非阻塞模式
在 socket 模型中,不同操作調用后會返回不同的套接字類型。socket() 方法會返回主動套接字,然后調用 listen() 方法,將主動套接字轉化為監聽套接字,此時,可以監聽來自客戶端的連接請求。最后,調用 accept() 方法接收到達的客戶端連接,并返回已連接套接字。
Redis套接字類型與非阻塞設置基于多路復用的高性能 I/O 模型
Linux 中的 IO 多路復用機制是指一個線程處理多個 IO 流,就是我們經常聽到的 select/epoll 機制。簡單來說,在 Redis 只運行單線程的情況下,該機制允許內核中,同時存在多個監聽套接字和已連接套接字。內核會一直監聽這些套接字上的連接請求或數據請求。一旦有請求到達,就會交給 Redis 線程處理,這就實現了一個 Redis 線程處理多個 IO 流的效果。
下圖就是基于多路復用的 Redis IO 模型。圖中的多個 FD 就是剛才所說的多個套接字。Redis 網絡框架調用 epoll 機制,讓內核監聽這些套接字。此時,Redis 線程不會阻塞在某一個特定的監聽或已連接套接字上,也就是說,不會阻塞在某一個特定的客戶端請求處理上。正因為此,Redis 可以同時和多個客戶端連接并處理請求,從而提升并發性。
基于多路復用的Redis高性能IO模型為了在請求到達時能通知到 Redis 線程,select/epoll 提供了基于事件的回調機制,即針對不同事件的發生,調用相應的處理函數。
這些事件會被放進一個事件隊列,Redis 單線程對該事件隊列不斷進行處理。這樣一來,Redis 無需一直輪詢是否有請求實際發生,這就可以避免造成 CPU 資源浪費。同時,Redis 在對事件隊列中的事件進行處理時,會調用相應的處理函數,這就實現了基于事件的回調。因為 Redis 一直在對事件隊列進行處理,所以能及時響應客戶端請求,提升 Redis 的響應性能。
以連接請求和讀數據請求為例,具體解釋一下:
這兩個請求分別對應 Accept 事件和 Read 事件,Redis 分別對這兩個事件注冊 accept 和 get 回調函數。當 Linux 內核監聽到有連接請求或讀數據請求時,就會觸發 Accept 事件和 Read 事件,此時,內核就會回調 Redis 相應的 accept 和 get 函數進行處理。
總結
以上是生活随笔為你收集整理的linux redis客户端_为什么单线程Redis能那么快?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 请问多少钱一盒啊?
- 下一篇: linux 内存取证_【取证流程】电子数