redis 和 memcached 有什麼區別?redis 的線程模型是什麼?爲何 redis 單線程卻能支撐高併發?

redis 和 memcached 有啥區別?

redis 支持複雜的數據結構

redis 相比 memcached 來講,擁有更多的數據結構,能支持更豐富的數據操做。若是須要緩存可以支持更復雜的結構和操做, redis 會是不錯的選擇。java

redis 原生支持集羣模式

在 redis3.x 版本中,便能支持 cluster 模式,而 memcached 沒有原生的集羣模式,須要依靠客戶端來實現往集羣中分片寫入數據。git

性能對比

因爲 redis 只使用單核,而 memcached 可使用多核,因此平均每個核上 redis 在存儲小數據時比 memcached 性能更高。而在 100k 以上的數據中,memcached 性能要高於 redis。雖然 redis 最近也在存儲大數據的性能上進行優化,可是比起 memcached,仍是稍有遜色。github

redis 的線程模型

redis 內部使用文件事件處理器 file event handler,這個文件事件處理器是單線程的,因此 redis 才叫作單線程的模型。它採用 IO 多路複用機制同時監聽多個 socket,將產生事件的 socket 壓入內存隊列中,事件分派器根據 socket 上的事件類型來選擇對應的事件處理器進行處理。redis

文件事件處理器的結構包含 4 個部分:編程

  • 多個 socket
  • IO 多路複用程序
  • 文件事件分派器
  • 事件處理器(鏈接應答處理器、命令請求處理器、命令回覆處理器)

多個 socket 可能會併發產生不一樣的操做,每一個操做對應不一樣的文件事件,可是 IO 多路複用程序會監聽多個 socket,會將產生事件的 socket 放入隊列中排隊,事件分派器每次從隊列中取出一個 socket,根據 socket 的事件類型交給對應的事件處理器進行處理。緩存

來看客戶端與 redis 的一次通訊過程:網絡

redis-single-thread-model

要明白,通訊是經過 socket 來完成的,不懂的同窗能夠先去看一看 socket 網絡編程。數據結構

首先,redis 服務端進程初始化的時候,會將 server socket 的 AE_READABLE 事件與鏈接應答處理器關聯。多線程

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

假設此時客戶端發送了一個 set key value 請求,此時 redis 中的 socket01 會產生 AE_READABLE 事件,IO 多路複用程序將 socket01 壓入隊列,此時事件分派器從隊列中獲取到 socket01 產生的 AE_READABLE 事件,因爲前面 socket01 的 AE_READABLE 事件已經與命令請求處理器關聯,所以事件分派器將事件交給命令請求處理器來處理。命令請求處理器讀取 socket01 的 key value 並在本身內存中完成 key value 的設置。操做完成後,它會將 socket01 的 AE_WRITABLE 事件與命令回覆處理器關聯。

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

這樣便完成了一次通訊。

爲啥 redis 單線程模型也能效率這麼高?

  • 純內存操做
  • 核心是基於非阻塞的 IO 多路複用機制
  • 單線程反而避免了多線程的頻繁上下文切換問題
相關文章
相關標籤/搜索