Redis 高效能IO模型

2021-10-18 17:26:30 字數 2395 閱讀 2503

redis核心結束與實戰 - 03

通常說redis 是單執行緒,主要是指 redis 的網路 io 和鍵值對讀寫是由乙個執行緒來完成的,這也是 redis 對外提供鍵值儲存服務的主要流程。但 redis 的其他功能,比如持久化、非同步刪除、集群資料同步等,其實是由額外的執行緒執行的。

目錄

一、多執行緒帶來的開銷:

二、單執行緒 redis 為什麼那麼快?

【依賴底層高效能的資料結構,依賴於多路復用機制】

1、基本i/o模型及其阻塞點   (潛在阻塞點:客戶端與redis建立連線, redis讀取客戶端資料)

2、非阻塞模式

3、基於多路復用的高效能i/o模型

多執行緒程式設計模式面臨的共享資源的併發訪問控制問題。併發訪問控制一直是多執行緒開發中的乙個難點問題,如果沒有精細的設計,比如說,只是簡單地採用乙個粗粒度互斥鎖,就會出現不理想的結果:即使增加了執行緒,大部分執行緒也在等待獲取訪問共享資源的互斥鎖,並行變序列,系統吞吐率並沒有隨著執行緒的增加而增加。而且,採用多執行緒開發一般會引入同步原語來保護共享資源的併發訪問,這也會降低系統**的易除錯性和可維護性。

redis 多方面設計選擇的乙個綜合結果:

redis 的大部分操作在記憶體上完成

它採用了高效的資料結構,例如雜湊表和跳表,這是它實現高效能的乙個重要原因。

redis 採用了多路復用機制,使其在網路 io 操作中能併發處理大量的客戶端請求,實現高吞吐率。

以 get 請求為例,redis為了處理乙個 get 請求,需要監聽客戶端請求(bind/listen),和客戶端建立連線(accept),從 socket 中讀取請求(recv),解析客戶端傳送請求(parse),根據請求型別讀取鍵值資料(get),最後給客戶端返回結果,即向 socket 中寫回資料(send)。下圖顯示了這一過程,其中,bind/listen、accept、recv、parse 和 send 屬於網路 io 處理,而 get 屬於鍵值資料操作。

既然 redis 是單執行緒,那麼,最基本的一種實現是在乙個執行緒中依次執行上面說的這些操作。但是在這裡的網路 io 操作中,有潛在的阻塞點,分別是 accept() 和 recv()

當 redis 監聽到乙個客戶端有連線請求,但一直未能成功建立起連線時,會阻塞在 accept() 函式這裡,導致其他客戶端無法和 redis 建立連線。

當 redis 通過 recv() 從乙個客戶端讀取資料時,如果資料一直沒有到達,redis 也會一直阻塞在 recv()。

這就導致 redis 整個執行緒阻塞,無法處理其他客戶端請求,效率很低。

-- 音訊06:49

socket 網路模型的非阻塞模式設定,主要體現在三個關鍵的函式呼叫上,如果想要使用 socket 非阻塞模式,就必須要了解這三個函式的呼叫返回型別和設定模式。在 socket 模型中,不同操作呼叫後會返回不同的套接字型別。socket() 方法會返回主動套接字,然後呼叫 listen() 方法,將主動套接字轉化為監聽套接字,此時,可以監聽來自客戶端的連線請求。最後,呼叫 accept() 方法接收到達的客戶端連線,並返回已連線套接字。

針對監聽套接字,我們可以設定非阻塞模式:當 redis 呼叫 accept() 但一直未有連線請求到達時,redis 執行緒可以返回處理其他操作,而不用一直等待。但是,你要注意的是,呼叫 accept() 時,已經存在監聽套接字了。雖然 redis 執行緒可以不用繼續等待,但是總得有機制繼續在監聽套接字上等待後續連線請求,並在有請求時通知 redis。類似的,我們也可以針對已連線套接字設定非阻塞模式:redis 呼叫 recv() 後,如果已連線套接字上一直沒有資料到達,redis 執行緒同樣可以返回處理其他操作。我們也需要有機制繼續監聽該已連線套接字,並在有資料達到時通知 redis。這樣才能保證 redis 執行緒,既不會像基本 io 模型中一直在阻塞點等待,也不會導致 redis 無法處理實際到達的連線請求或資料。

linux 中的 io 多路復用機制是指乙個執行緒處理多個 io 流,就是我們經常聽到的 select/epoll 機制。

簡單來說,在 redis 只執行單執行緒的情況下,該機制允許核心中,同時存在多個監聽套接字和已連線套接字。核心會一直監聽這些套接字上的連線請求或資料請求。一旦有請求到達,就會交給 redis 執行緒處理,這就實現了乙個 redis 執行緒處理多個 io 流的效果。

注:2020 年 5 月,redis 6.0 的穩定版發布了,redis 6.0 中提出了多執行緒模型。那麼,這個多執行緒模型和這節課所說的 io 模型有什麼關聯?會引入複雜的併發控制問題嗎?會給 redis 6.0 帶來多大提公升?

Redis高效能IO模型

首先,要釐清乙個事實,我們通常說,redis 是單執行緒,主要是指redis 的網路 io和鍵值對讀寫是由乙個執行緒來完成的,這也是 redis 對外提供鍵值儲存服務的主要流程。但 redis 的其他功能,比如持久化 非同步刪除 集群資料同步等,其實是由額外的執行緒執行的。所以,嚴格來說,redis...

Kafka如何實現高效能IO?

雖然kafka的sdk提供了單條訊息傳送,但實際上,kafka 的客戶端 sdk 在實現訊息傳送邏輯的時候,採用了非同步批量傳送的機制 當你呼叫 send 方法傳送一條訊息之後,無論你是同步傳送還是非同步傳送,kafka 都不會立即就把這條訊息傳送出去。它會先把這條訊息,存放在記憶體中快取起來,然後...

Kafka如何實現高效能IO?

雖然kafka的sdk提供了單條訊息傳送,但實際上,kafka 的客戶端 sdk 在實現訊息傳送邏輯的時候,採用了非同步批量傳送的機制 當你呼叫 send 方法傳送一條訊息之後,無論你是同步傳送還是非同步傳送,kafka 都不會立即就把這條訊息傳送出去。它會先把這條訊息,存放在記憶體中快取起來,然後...