突破Java面試(20)-Redis線程模型

1 面試題

redis和memcached有什麼區別?redis的線程模型是什麼?爲何單線程的redis比多線程的memcached效率要高得多(爲何redis是單線程的可是還能夠支撐高併發)?java

2 考點分析

這個是問redis的時候,最基本的問題,redis最基本的一個內部原理和特色,就是redis其實是個單線程工做模型,你要是這個都不知道,那後面玩兒redis的時候,出了問題豈不是什麼都不知道?react

還有可能面試官會問問你redis和memcached的區別,不過說實話,最近這兩年,做爲面試官都不太喜歡這麼問了,memched是早些年各大互聯網公司經常使用的緩存方案,可是如今近幾年基本都是redis,沒什麼公司用memcached了git

額外的友情提示 同窗,你要是如今還不知道redis和memcached是啥?那你趕忙百度一下redis入門和memcahced入門,簡單啓動一下,而後試一下幾個簡單操做,先感覺一下。接着回來繼續看,我以爲1小時之內你就搞定了。 另一個友情提示,要聽明白redis的線程模型,你須要瞭解socket網絡相關的基本知識,若是不懂,那我以爲你java沒學好吧。初學者都該學習java的socket網絡通訊相關知識github

4 詳解

4.1 redis和memcached的區別

這個事兒吧,你能夠比較出N多個區別來,可是我仍是採起redis做者給出的幾個比較吧面試

4.1.1 Redis支持服務器端的數據操做

Redis相比Memcached來講,擁有更多的數據結構和並支持更豐富的數據操做redis

  • 一般在Memcached裏,你須要將數據拿到客戶端來進行相似的修改再set回去,這大大增長了網絡IO的次數和數據體積
  • 在Redis中,這些複雜的操做一般和通常的GET/SET同樣高效。因此,若是須要緩存可以支持更復雜的結構和操做,那麼Redis會是不錯的選擇。

4.1.2 內存使用效率對比

使用簡單的KV存儲的話,Memcached的內存利用率更高,而若是Redis採用hash結構來作key-value存儲,因爲其組合式的壓縮,其內存利用率會高於Memcached。緩存

4.1.3 性能對比

  • Redis只使用單核
  • Memcached可使用多核

因此平均每個核上Redis在存儲小數據時比Memcached性能更高 而在100k以上的數據中,Memcached性能要高於Redis,雖然Redis最近也在存儲大數據的性能上進行優化,可是比起Memcached,稍有遜色。服務器

4.1.4 集羣模式

  • memcached沒有原生的集羣模式,須要依靠客戶端來實現往集羣中分片寫入數據
  • 可是redis目前是原生支持cluster模式的,redis官方就是支持redis cluster集羣模式的,比memcached來講要更好

4.2 Redis的線程模型

4.2.1 文件事件處理器

redis基於reactor模式開發了網絡事件處理器,這個處理器叫作文件事件處理器,file event handler網絡

這個文件事件處理器,是單線程的,redis才叫作單線程的模型,採用IO多路複用機制同時監聽多個socket,根據socket上的事件來選擇對應的事件處理器來處理這個事件。數據結構

若是被監聽的socket準備好執行acceptreadwriteclose等操做時,跟操做對應的文件事件就會產生,這個時候文件事件處理器就會調用以前關聯好的事件處理器來處理對應事件。

文件事件處理器是單線程模式運行的,可是經過IO多路複用機制監聽多個socket,實現高性能的網絡通訊模型,又能夠跟內部其餘單線程的模塊進行對接,保證了redis內部的線程模型的簡單性。

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

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

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

而後一個socket的事件處理完以後,IO多路複用程序纔會將隊列中的下一個socket給事件分派器。文件事件分派器會根據每一個socket當前產生的事件,來選擇對應的事件處理器來處理。

4.2.2 文件事件

當socket變得可讀時(好比客戶端對redis執行write/close操做),或者有新的能夠應答的sccket出現時(客戶端對redis執行connect操做),socket就會產生一個AE_READABLE事件

當socket變得可寫的時候(客戶端對redis執行read操做),socket會產生一個AE_WRITABLE事件。

IO多路複用程序能夠同時監聽AE_REABLE和AE_WRITABLE兩種事件,要是一個socket同時產生了AE_READABLE和AE_WRITABLE兩種事件,那麼文件事件分派器優先處理AE_REABLE事件,而後纔是AE_WRITABLE事件。

4.2.3 文件事件處理器

若是是客戶端要鏈接redis,那麼會爲socket關聯鏈接應答處理器 若是是客戶端要寫數據到redis,那麼會爲socket關聯命令請求處理器 若是是客戶端要從redis讀數據,那麼會爲socket關聯命令回覆處理器

4.2.4 客戶端與redis通訊的一次流程

在redis啓動初始化的時候,redis會將鏈接應答處理器跟AE_READABLE事件關聯起來,接着若是一個客戶端跟redis發起鏈接,此時會產生一個AE_READABLE事件,而後由鏈接應答處理器來處理跟客戶端創建鏈接,建立客戶端對應的socket,同時將這個socket的AE_READABLE事件跟命令請求處理器關聯起來。

當客戶端向redis發起請求的時候(不論是讀請求仍是寫請求,都同樣),首先就會在socket產生一個AE_READABLE事件,而後由對應的命令請求處理器來處理。這個命令請求處理器就會從socket中讀取請求相關數據,而後進行執行和處理。

接着redis這邊準備好了給客戶端的響應數據以後,就會將socket的AE_WRITABLE事件跟命令回覆處理器關聯起來,當客戶端這邊準備好讀取響應數據時,就會在socket上產生一個AE_WRITABLE事件,會由對應的命令回覆處理器來處理,就是將準備好的響應數據寫入socket,供客戶端來讀取。

命令回覆處理器寫完以後,就會刪除這個socket的AE_WRITABLE事件和命令回覆處理器的關聯關係。

4.3 redis的單線程模型爲什麼效率高

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

X 交流學習

Java交流羣

博客

Github

相關文章
相關標籤/搜索