Redis的單執行緒為什麼快?(網路IO模型)

2021-10-25 07:28:54 字數 1651 閱讀 3278

寫這篇redis單執行緒為什麼快,redis6.x已經發布快一年了,但是絕大公司還是在使用redis5.x版本,因為redis5.x已經足夠給中小型企業提供支援了,甚至有些大型公司還在使用單執行緒redis。

首先,在此說明,redis6.0以前真的是單執行緒嗎?這裡分為兩個方面:

反正問題乙個接乙個

redis作者曾經說過,不想讓redis變得更加複雜,也就是說採用多執行緒必須要有良好的設計,就算是多執行緒訪問,還要維護共享資源的問題,已經加鎖,隨著執行緒變多,鎖也就成為了瓶頸,因為要等待鎖釋放,到最後也就會成為序列化。

redis快可以從三個方面切入:

所有的系統i/o都分為兩個階段:等待就緒和操作。舉例來說,讀函式,分為等待系統可讀和真正的讀; 同理,寫函式分為等待網絡卡可以寫和真正的寫。

需要說明的是等待就緒的阻塞是不使用cpu的,是在「空等」;而真正的讀寫操作的阻塞是使用cpu的,真正在」幹活」,而且這個過程非常快,屬於memory copy,頻寬通常在1gb/s級別以上,可以理解為基本不耗時。

這些方面都是以socket來說,乙個socket只***了四元組唯一就可以建立乙個連線,每個連線就會對應乙個fd,建立後核心就會維護乙個buffer,這個buffer大小應該是mtu的大小,傳送的資料都會在這個buffer裡。

阻塞就代表了應用程式向服務端讀取資料時,核心的這個buffer是空的,就會一直等著核心把資料準備好,有資料了就從核心copy到使用者空間。整個過程是同步阻塞的。

阻塞點發生再accept() 和 recv()這兩個系統呼叫。從redis角度來說,當 redis 監聽到乙個客戶端有連線請求,但一直未能成功建立起連線時,會阻塞在 accept() 函式這裡,導致其他客戶端無法和 redis 建立連線。同樣的,當 redis 通過 recv() 從乙個客戶端讀取資料時,如果資料一直沒有到達,redis 也會一直阻塞在 recv()。

socket中也可以設定非阻塞模式,也就是說accept()指向後有連線建立就放回乙個fd,若是沒有返回-1,同理recv也是的。

這樣的如果是redis再非阻塞的情況下,就可以有空閒時間去處理別的事情,同時還是會一直監聽連線的到達的。

這樣才能保證 redis 執行緒,既不會像基本 io 模型中一直在阻塞點等待,也不會導致 redis 無法處理實際到達的連線請求或資料。

最後就是多路復用了,多路復用器一次性可以處理多個fd。以redis的epoll為例,當有建立好連線後有fd4時,epoll會呼叫epoll_create函式建立紅黑樹返回epfd5(fd自增的),再呼叫epoll_ctl(「epfd5」,操作符比如add新增,新的fd3),就會把fd3放到了紅黑樹中,再觸發乙個中斷,中斷就會延申,把有狀態的fd放到乙個鍊錶中(這樣就避免了select/poll的遍歷了),再呼叫epoll_wait告訴redis可讀可寫的fd,redis再recv()。(只要是程式直接讀寫,它就是同步模型)

即便程式不呼叫核心,核心也會隨著中斷的發生完成有fd的狀態設定,redis只需要呼叫wait取走有狀態的fd的結果集進行對應的操作。

這樣redis 無需一直輪詢是否有請求實際發生,這就可以避免造成 cpu 資源浪費。

單執行緒的 Redis 為什麼這麼快

redis採用的是基於記憶體的 單程序單執行緒模型的kv資料庫,由c語言編寫。官方提供的資料是可以達到1000000 的qps 每秒內查詢次數 這個資料不比採用單程序多執行緒的同樣基於記憶體的kv資料庫memcached查。為了更好的回答和理解redis為什麼有這好的效能,我們從以下兩個問題來解答 ...

Redis是單執行緒,為什麼這麼快?

為什麼這麼快,簡單說法 1.redis是基於記憶體的,記憶體的讀寫速度非常快 2.redis是單執行緒的,省去了很多上下文切換執行緒的時間 3.redis使用多路復用技術,可以處理併發的連線 較詳細的解釋 1 完全基於記憶體,絕大部分請求是純粹的記憶體操作,非常快速。資料存在記憶體中,類似於hash...

redis單執行緒為什麼速度快

1 基本概念 一塊2.gghz的cpu,一秒可以處理2.6 10 9 條命令,一條指令就是0.38ns,切換一次執行緒耗時2000ns,切換執行緒開銷是大的。2 那為什麼有多執行緒 硬碟訪問時間遠遠大於記憶體。當cpu在等待硬碟的時候,它可以先去做別的事情,比如等硬碟要乙個小時,儲存現場需要十五分鐘...