Redis經(jīng)典設(shè)計(jì)模式-Reactor

每個(gè)經(jīng)典的系統(tǒng)服務(wù)組件,我們總是能發(fā)現(xiàn)其賴以高性能的機(jī)制。
所以我們這次也是一樣镰惦,借著Redis的專題,用實(shí)例來(lái)寫點(diǎn)對(duì)Reactor模式的理解犬绒。
首先我們免不了俗旺入,簡(jiǎn)單介紹下Reactor的相關(guān)概念:

Reactor對(duì)象圖

Reator序列圖

Reactor模式的角色構(gòu)成(Reactor模式一共有5中角色構(gòu)成):

Handle(句柄或描述符,在Windows下稱為句柄,在Linux下稱為描述符):本質(zhì)上表示一種資源(比如說(shuō)文件描述符茵瘾,或是針對(duì)網(wǎng)絡(luò)編程中的socket描述符)礼华,是由操作系統(tǒng)提供的;該資源用于表示一個(gè)個(gè)的事件拗秘,事件既可以來(lái)自于外部圣絮,也可以來(lái)自于內(nèi)部;外部事件比如說(shuō)客戶端的連接請(qǐng)求雕旨,客戶端發(fā)送過(guò)來(lái)的數(shù)據(jù)等扮匠;內(nèi)部事件比如說(shuō)操作系統(tǒng)產(chǎn)生的定時(shí)事件等。它本質(zhì)上就是一個(gè)文件描述符凡涩,Handle是事件產(chǎn)生的發(fā)源地棒搜。

Synchronous Event Demultiplexer(同步事件分離器):它本身是一個(gè)系統(tǒng)調(diào)用,用于等待事件的發(fā)生(事件可能是一個(gè)活箕,也可能是多個(gè))力麸。調(diào)用方在調(diào)用它的時(shí)候會(huì)被阻塞,一直阻塞到同步事件分離器上有事件產(chǎn)生為止讹蘑。對(duì)于Linux來(lái)說(shuō)末盔,同步事件分離器指的就是常用的I/O多路復(fù)用機(jī)制,比如說(shuō)select座慰、poll、epoll等翠拣。在Java NIO領(lǐng)域中版仔,同步事件分離器對(duì)應(yīng)的組件就是Selector;對(duì)應(yīng)的阻塞方法就是select方法误墓。

Event Handler(事件處理器):本身由多個(gè)回調(diào)方法構(gòu)成蛮粮,這些回調(diào)方法構(gòu)成了與應(yīng)用相關(guān)的對(duì)于某個(gè)事件的反饋機(jī)制。在Java NIO領(lǐng)域中并沒(méi)有提供事件處理器機(jī)制讓我們調(diào)用或去進(jìn)行回調(diào)谜慌,是由我們自己編寫代碼完成的然想。Netty相比于Java NIO來(lái)說(shuō),在事件處理器這個(gè)角色上進(jìn)行了一個(gè)升級(jí)欣范,它為我們開發(fā)者提供了大量的回調(diào)方法变泄,供我們?cè)谔囟ㄊ录a(chǎn)生時(shí)實(shí)現(xiàn)相應(yīng)的回調(diào)方法進(jìn)行業(yè)務(wù)邏輯的處理,即恼琼,ChannelHandler妨蛹。ChannelHandler中的方法對(duì)應(yīng)的都是一個(gè)個(gè)事件的回調(diào)。

Concrete Event Handler(具體事件處理器):是事件處理器的實(shí)現(xiàn)晴竞。它本身實(shí)現(xiàn)了事件處理器所提供的各種回調(diào)方法蛙卤,從而實(shí)現(xiàn)了特定于業(yè)務(wù)的邏輯。它本質(zhì)上就是我們所編寫的一個(gè)個(gè)的處理器實(shí)現(xiàn)。

Initiation Dispatcher(初始分發(fā)器):實(shí)際上就是Reactor角色颤难。它本身定義了一些規(guī)范神年,這些規(guī)范用于控制事件的調(diào)度方式,同時(shí)又提供了應(yīng)用進(jìn)行事件處理器的注冊(cè)行嗤、刪除等設(shè)施已日。它本身是整個(gè)事件處理器的核心所在,Initiation Dispatcher會(huì)通過(guò)Synchronous Event Demultiplexer來(lái)等待事件的發(fā)生昂验。一旦事件發(fā)生捂敌,Initiation Dispatcher首先會(huì)分離出每一個(gè)事件,然后調(diào)用事件處理器既琴,最后調(diào)用相關(guān)的回調(diào)方法來(lái)處理這些事件占婉。Netty中ChannelHandler里的一個(gè)個(gè)回調(diào)方法都是由bossGroup或workGroup中的某個(gè)EventLoop來(lái)調(diào)用的。


根據(jù)并發(fā)支撐要求等級(jí)分為以下幾種模式


單線程Reactor模式
這是Redis目前采用的實(shí)現(xiàn)方式甫恩,通過(guò)主線程去響應(yīng)處理IO事件逆济,逐條執(zhí)行命令;而其中Redis能夠支撐高并發(fā)和快速響應(yīng)的原因如下:

  1. redis是基于內(nèi)存的磺箕,內(nèi)存的讀寫速度非辰被牛快。
  2. redis是單線程的松靡,省去了很多上下文切換線程的時(shí)間简僧。
  3. redis使用多路復(fù)用技術(shù),可以處理并發(fā)的連接雕欺。

單線程Reactor模式

該模式整體流程是:
① 服務(wù)器端的Reactor是一個(gè)線程對(duì)象岛马,該線程會(huì)啟動(dòng)事件循環(huán),并使用Selector來(lái)實(shí)現(xiàn)IO的多路復(fù)用屠列。注冊(cè)一個(gè)Acceptor事件處理器到Reactor中啦逆,Acceptor事件處理器所關(guān)注的事件是ACCEPT事件,這樣Reactor會(huì)監(jiān)聽客戶端向服務(wù)器端發(fā)起的連接請(qǐng)求事件(ACCEPT事件)笛洛。
② 客戶端向服務(wù)器端發(fā)起一個(gè)連接請(qǐng)求夏志,Reactor監(jiān)聽到了該ACCEPT事件的發(fā)生并將該ACCEPT事件派發(fā)給相應(yīng)的Acceptor處理器來(lái)進(jìn)行處理。Acceptor處理器通過(guò)accept()方法得到與這個(gè)客戶端對(duì)應(yīng)的連接(SocketChannel)苛让,然后將該連接所關(guān)注的READ事件以及對(duì)應(yīng)的READ事件處理器注冊(cè)到Reactor中沟蔑,這樣一來(lái)Reactor就會(huì)監(jiān)聽該連接的READ事件了◎蚬睿或者當(dāng)你需要向客戶端發(fā)送數(shù)據(jù)時(shí)溉贿,就向Reactor注冊(cè)該連接的WRITE事件和其處理器。
③ 當(dāng)Reactor監(jiān)聽到有讀或者寫事件發(fā)生時(shí)浦旱,將相關(guān)的事件派發(fā)給對(duì)應(yīng)的處理器進(jìn)行處理宇色。比如,讀處理器會(huì)通過(guò)SocketChannel的read()方法讀取數(shù)據(jù),此時(shí)read()操作可以直接讀取到數(shù)據(jù)宣蠕,而不會(huì)堵塞與等待可讀的數(shù)據(jù)到來(lái)例隆。
④ 每當(dāng)處理完所有就緒的感興趣的I/O事件后,Reactor線程會(huì)再次執(zhí)行select()阻塞等待新的事件就緒并將其分派給對(duì)應(yīng)處理器進(jìn)行處理抢蚀。
根據(jù)Redis單線程處理設(shè)計(jì)镀层,后續(xù)的升級(jí)演進(jìn),猜測(cè)很可能是走單線程多Reactor模式
一個(gè)典型的Redis最佳實(shí)踐是皿曲,不推薦使用big key唱逢,因?yàn)閎ig key的操作會(huì)降低Reactor的響應(yīng)速度。單線程多Reactor模式可以有效將連接動(dòng)作和讀寫動(dòng)作分離屋休,提高吞吐量坞古。TODO:后續(xù)的文章會(huì)寫一個(gè)關(guān)于redis生產(chǎn)使用過(guò)程中,因輸入緩沖爆滿導(dǎo)致redis崩潰的例子劫樟。


線程池Reactor模式

線程池Reactor模式

相對(duì)于單線程Reactor模式痪枫,Reactor將業(yè)務(wù)相關(guān)的解碼+計(jì)算+編碼工作(非I/O操作),交付給了線程池叠艳,Reactor無(wú)需關(guān)注業(yè)務(wù)相關(guān)的工作奶陈,其中線程池中的線程能夠復(fù)用,也不會(huì)引入太多的線程創(chuàng)建和切換的開銷附较;從而簡(jiǎn)化Reactor的工作吃粒,使得Reactor專注accept(),read()和write()等IO業(yè)務(wù)拒课;


線程池多Reactor模式

線程池多Reactor模式

該模式整體流程是:
① 注冊(cè)一個(gè)Acceptor事件處理器到mainReactor中声搁,Acceptor事件處理器所關(guān)注的事件是ACCEPT事件,這樣mainReactor會(huì)監(jiān)聽客戶端向服務(wù)器端發(fā)起的連接請(qǐng)求事件(ACCEPT事件)捕发。啟動(dòng)mainReactor的事件循環(huán)。
② 客戶端向服務(wù)器端發(fā)起一個(gè)連接請(qǐng)求很魂,mainReactor監(jiān)聽到了該ACCEPT事件并將該ACCEPT事件派發(fā)給Acceptor處理器來(lái)進(jìn)行處理扎酷。Acceptor處理器通過(guò)accept()方法得到與這個(gè)客戶端對(duì)應(yīng)的連接(SocketChannel),然后將這個(gè)SocketChannel傳遞給subReactor線程池遏匆。
③ subReactor線程池分配一個(gè)subReactor線程給這個(gè)SocketChannel法挨,即,將SocketChannel關(guān)注的READ事件以及對(duì)應(yīng)的READ事件處理器注冊(cè)到subReactor線程中幅聘。當(dāng)然你也注冊(cè)WRITE事件以及WRITE事件處理器到subReactor線程中以完成I/O寫操作凡纳。Reactor線程池中的每一Reactor線程都會(huì)有自己的Selector、線程和分發(fā)的循環(huán)邏輯帝蒿。
④ 當(dāng)有I/O事件就緒時(shí)荐糜,相關(guān)的subReactor就將事件派發(fā)給響應(yīng)的處理器處理。注意,這里subReactor線程只負(fù)責(zé)完成I/O的read()操作暴氏,在讀取到數(shù)據(jù)后將業(yè)務(wù)邏輯的處理放入到線程池中完成延塑,若完成業(yè)務(wù)邏輯后需要返回?cái)?shù)據(jù)給客戶端,則相關(guān)的I/O的write操作還是會(huì)被提交回subReactor線程來(lái)完成答渔。


【多Reactor線程模式將“接受客戶端的連接請(qǐng)求”和“與該客戶端的通信”分在了兩個(gè)Reactor線程來(lái)完成】
mainReactor完成接收客戶端連接請(qǐng)求的操作关带,它不負(fù)責(zé)與客戶端的通信,而是將建立好的連接轉(zhuǎn)交給subReactor線程來(lái)完成與客戶端的通信沼撕,這樣一來(lái)就不會(huì)因?yàn)閞ead()數(shù)據(jù)量太大而導(dǎo)致后面的客戶端連接請(qǐng)求得不到即時(shí)處理的情況宋雏。并且多Reactor線程模式在海量的客戶端并發(fā)請(qǐng)求的情況下,還可以通過(guò)實(shí)現(xiàn)subReactor線程池來(lái)將海量的連接分發(fā)給多個(gè)subReactor線程务豺,在多核的操作系統(tǒng)中這能大大提升應(yīng)用的負(fù)載和吞吐量磨总。


TODO:等有時(shí)間了實(shí)現(xiàn)一個(gè)多Reactor線程池模式的Demo放上來(lái)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末冲呢,一起剝皮案震驚了整個(gè)濱河市舍败,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌敬拓,老刑警劉巖邻薯,帶你破解...
    沈念sama閱讀 211,948評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異乘凸,居然都是意外死亡厕诡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門营勤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)灵嫌,“玉大人,你說(shuō)我怎么就攤上這事葛作∈傩撸” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵赂蠢,是天一觀的道長(zhǎng)绪穆。 經(jīng)常有香客問(wèn)我,道長(zhǎng)虱岂,這世上最難降的妖魔是什么玖院? 我笑而不...
    開封第一講書人閱讀 56,521評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮第岖,結(jié)果婚禮上难菌,老公的妹妹穿的比我還像新娘。我一直安慰自己蔑滓,他們只是感情好郊酒,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評(píng)論 6 386
  • 文/花漫 我一把揭開白布遇绞。 她就那樣靜靜地躺著,像睡著了一般猎塞。 火紅的嫁衣襯著肌膚如雪试读。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,842評(píng)論 1 290
  • 那天荠耽,我揣著相機(jī)與錄音钩骇,去河邊找鬼。 笑死铝量,一個(gè)胖子當(dāng)著我的面吹牛倘屹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播慢叨,決...
    沈念sama閱讀 38,997評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼纽匙,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了拍谐?” 一聲冷哼從身側(cè)響起烛缔,我...
    開封第一講書人閱讀 37,741評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎轩拨,沒(méi)想到半個(gè)月后践瓷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,203評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亡蓉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評(píng)論 2 327
  • 正文 我和宋清朗相戀三年晕翠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砍濒。...
    茶點(diǎn)故事閱讀 38,673評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淋肾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出爸邢,到底是詐尸還是另有隱情樊卓,我是刑警寧澤,帶...
    沈念sama閱讀 34,339評(píng)論 4 330
  • 正文 年R本政府宣布杠河,位于F島的核電站简识,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏感猛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評(píng)論 3 313
  • 文/蒙蒙 一奢赂、第九天 我趴在偏房一處隱蔽的房頂上張望陪白。 院中可真熱鬧,春花似錦膳灶、人聲如沸咱士。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)序厉。三九已至锐膜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弛房,已是汗流浹背道盏。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留文捶,地道東北人荷逞。 一個(gè)月前我還...
    沈念sama閱讀 46,394評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像粹排,于是被迫代替她去往敵國(guó)和親种远。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容

  • 要無(wú)障礙閱讀本文顽耳,需要對(duì)NIO有一個(gè)大概的了解坠敷,起碼要可以寫一個(gè)NIO的Hello World。 說(shuō)到NIO射富、Ne...
    CoderBear閱讀 1,718評(píng)論 0 3
  • 一. 為什么需要 解決多請(qǐng)求問(wèn)題膝迎,但是這些請(qǐng)求不需要一直占有整個(gè)線程資源(比如IO操作時(shí)不必一直等待),所以不適合...
    Joseph1453閱讀 7,840評(píng)論 0 11
  • 原文出處:https://www.cnblogs.com/winner-0715/p/8733787.html 在...
    小波同學(xué)閱讀 364評(píng)論 0 0
  • 本文是Netty文集中“Netty 那些事兒”系列的文章辉浦。主要結(jié)合在開發(fā)實(shí)戰(zhàn)中弄抬,我們遇到的一些“奇奇怪怪”的問(wèn)題,...
    tomas家的小撥浪鼓閱讀 15,458評(píng)論 3 35
  • 今天感恩節(jié)哎宪郊,感謝一直在我身邊的親朋好友掂恕。感恩相遇!感恩不離不棄弛槐。 中午開了第一次的黨會(huì)懊亡,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,559評(píng)論 0 11