1. 程式人生 > 其它 >為什麼Redis 是單執行緒卻能支撐高併發?

為什麼Redis 是單執行緒卻能支撐高併發?

redis 和 memcached 有什麼區別?redis 的執行緒模型是什麼?為什麼 redis 單執行緒卻能支撐高併發?

這個是問 redis 的時候,最基本的問題吧,redis 最基本的一個內部原理和特點,就是 redis 實際上是個單執行緒工作模型,你要是這個都不知道,那後面玩兒 redis 的時候,出了問題豈不是什麼都不知道?

還有可能面試官會問問你 redis 和 memcached 的區別,但是 memcached 是早些年各大網際網路公司常用的快取方案,但是現在近幾年基本都是 redis,沒什麼公司用 memcached 了。

redis 和 memcached 有啥區別?

redis 支援複雜的資料結構

redis 相比 memcached 來說,擁有更多的資料結構,能支援更豐富的資料操作。如果需要快取能夠支援更復雜的結構和操作, redis 會是不錯的選擇。

redis 原生支援叢集模式

在 redis3.x 版本中,便能支援 cluster 模式,而 memcached 沒有原生的叢集模式,需要依靠客戶端來實現往叢集中分片寫入資料。

效能對比

由於 redis 只使用單核,而 memcached 可以使用多核,所以平均每一個核上 redis 在儲存小資料時比 memcached 效能更高。而在 100k 以上的資料中,memcached 效能要高於 redis,雖然 redis 最近也在儲存大資料的效能上進行優化,但是比起 memcached,還是稍有遜色。

 

redis 的執行緒模型

redis 內部使用檔案事件處理器 file event handler,這個檔案事件處理器是單執行緒的,所以 redis 才叫做單執行緒的模型。它採用 IO 多路複用機制同時監聽多個 socket,根據 socket 上的事件來選擇對應的事件處理器進行處理。

檔案事件處理器的結構包含 4 個部分:

    • 多個 socket
    • IO 多路複用程式
    • 檔案事件分派器
    • 事件處理器(連線應答處理器、命令請求處理器、命令回覆處理器)

 

多個 socket 可能會併發產生不同的操作,每個操作對應不同的檔案事件,但是 IO 多路複用程式會監聽多個 socket,會將 socket 產生的事件放入佇列中排隊,事件分派器每次從佇列中取出一個事件,把該事件交給對應的事件處理器進行處理。

來看客戶端與 redis 的一次通訊過程(圖片若不清晰,請右擊在新標籤中開啟圖片):

 

 

客戶端 socket01 向 redis 的 server socket 請求建立連線,此時 server socket 會產生一個 AE_READABLE 事件,IO 多路複用程式監聽到 server socket 產生的事件後,將該事件壓入佇列中。檔案事件分派器從佇列中獲取該事件,交給連線應答處理器。連線應答處理器會建立一個能與客戶端通訊的 socket01,並將該 socket01 的 AE_READABLE 事件與命令請求處理器關聯。

假設此時客戶端傳送了一個 set key value 請求,此時 redis 中的 socket01 會產生 AE_READABLE 事件,IO 多路複用程式將事件壓入佇列,此時事件分派器從佇列中獲取到該事件,由於前面 socket01 的 AE_READABLE 事件已經與命令請求處理器關聯,因此事件分派器將事件交給命令請求處理器來處理。命令請求處理器讀取 socket01 的 key value 並在自己記憶體中完成 key value 的設定。操作完成後,它會將 socket01 的 AE_WRITABLE 事件與命令回覆處理器關聯。

如果此時客戶端準備好接收返回結果了,那麼 redis 中的 socket01 會產生一個 AE_WRITABLE 事件,同樣壓入佇列中,事件分派器找到相關聯的命令回覆處理器,由命令回覆處理器對 socket01 輸入本次操作的一個結果,比如 ok,之後解除 socket01 的 AE_WRITABLE 事件與命令回覆處理器的關聯。

這樣便完成了一次通訊。

為啥 redis 單執行緒模型也能效率這麼高?

    • 純記憶體操作
    • 核心是基於非阻塞的 IO 多路複用機制
    • 單執行緒反而避免了多執行緒的頻繁上下文切換問題

 轉自:

https://link.zhihu.com/?target=https%3A//www.cnblogs.com/jian-ge/p/10097244.html