curl 请求没反应_理解Redis的反应堆模式
歡迎關(guān)注 接收最新文章!
1. Redis的網(wǎng)絡(luò)模型
Redis基于Reactor模式(反應(yīng)堆模式)開(kāi)發(fā)了自己的網(wǎng)絡(luò)模型,形成了一個(gè)完備的基于IO復(fù)用的事件驅(qū)動(dòng)服務(wù)器,但是不由得浮現(xiàn)幾個(gè)問(wèn)題:
- 為什么要使用Reactor模式呢?
- Redis如何實(shí)現(xiàn)自己的Reactor模式?
2. Reactor模式的背景
單純的epoll/kqueue可以單機(jī)支持?jǐn)?shù)萬(wàn)并發(fā),單純從性能的角度而言毫無(wú)問(wèn)題,但是技術(shù)實(shí)現(xiàn)和軟件設(shè)計(jì)仍然存在一些差異。設(shè)想這樣一種場(chǎng)景:
- epoll/kqueue將收集到的可讀寫(xiě)事件全部放入隊(duì)列中等待業(yè)務(wù)線程的處理,此時(shí)線程池的工作線程拿到任務(wù)進(jìn)行處理,實(shí)際場(chǎng)景中可能有很多種請(qǐng)求類(lèi)型,工作線程每拿到一種任務(wù)就進(jìn)行相應(yīng)的處理,處理完成之后繼續(xù)處理其他類(lèi)型的任務(wù);
- 工作線程需要關(guān)注各種不同類(lèi)型的請(qǐng)求,對(duì)于不同的請(qǐng)求選擇不同的處理方法,因此請(qǐng)求類(lèi)型的增加會(huì)讓工作線程復(fù)雜度增加,維護(hù)起來(lái)也變得越來(lái)越困難;
作為吃貨的你,如果還是沒(méi)聽(tīng)懂,不用著急,想象一下吃飯的場(chǎng)景:
城南大熊飯店在來(lái)客高峰期服務(wù)員快速地接待了很多顧客,有的顧客點(diǎn)涼菜,有的點(diǎn)熱菜,有的點(diǎn)主食,有的點(diǎn)飲料等等,在后廚如果人員沒(méi)有分工,那么廚師A一會(huì)兒弄涼菜一會(huì)弄主食,廚師B一會(huì)兒弄熱菜一會(huì)兒弄飲料,廚師C一會(huì)兒弄主食一會(huì)兒弄火鍋.....雖然最終也響應(yīng)了顧客的需求,但是把這幫廚師累夠嗆并且廚師都是全棧廚師(FullStack),對(duì)飯店來(lái)說(shuō)招個(gè)這樣的廚師非常不容易而且薪水也高,老板孫大熊很苦惱。
當(dāng)局者迷旁觀者清,孫大熊找到了他MBA的同學(xué)李明訴說(shuō)這個(gè)苦惱,李明說(shuō)專(zhuān)業(yè)的人做專(zhuān)業(yè)的事情才是王道,涼菜的有涼菜廚師、熱菜有熱菜廚師、主食有主食廚師,如果有新增的菜系菜品,那就再找個(gè)專(zhuān)門(mén)做這個(gè)菜品的廚師就可以了,這樣解決了廚師業(yè)務(wù)能力要求高、飯店擴(kuò)張慢的問(wèn)題,孫大熊頻頻點(diǎn)頭,感覺(jué)自己花錢(qián)買(mǎi)的這個(gè)MBA算是瞎了,回去之后進(jìn)行改進(jìn),果然有很大的改善,孫大熊又開(kāi)始嘚瑟了。
上面的場(chǎng)景其實(shí)和高并發(fā)網(wǎng)絡(luò)模型很相似,如果我們?cè)趀poll/kqueue的基礎(chǔ)上進(jìn)行業(yè)務(wù)區(qū)分,并且對(duì)每一種業(yè)務(wù)設(shè)置相應(yīng)的處理函數(shù),每次來(lái)任務(wù)之后對(duì)任務(wù)進(jìn)行識(shí)別和分發(fā),每種處理函數(shù)只處理一種業(yè)務(wù),這種模型更加符合OO的設(shè)計(jì)理念,這也是Reactor反應(yīng)堆模式的設(shè)計(jì)思路。
3. Reactor模式
基于Reactor的組件陣營(yíng)非常強(qiáng)大:
- Java NIO
- Netty
- libevent/libuv
- Redis
反應(yīng)堆模式是一種對(duì)象行為的設(shè)計(jì)模式,主要同于同步IO,異步IO有Proactor模式,這里不詳細(xì)講述Proactor模式,二者的主要區(qū)別就是Reactor是同步IO,Proactor是異步IO,理論上Proactor效率更高,但是Proactor模式需要操作系統(tǒng)在內(nèi)核層面對(duì)異步IO進(jìn)行支持,Linux的Boost.asio就是Proactor模式的代表,Windows有IOCP。
網(wǎng)上比較經(jīng)典的一張Reactor模式的類(lèi)圖:
圖中給出了5個(gè)部件分別為:
- handle 可以理解為讀寫(xiě)事件 可以注冊(cè)到Reactor進(jìn)行監(jiān)控
- Sync event demultiplexer 可以理解為epoll/kqueue/select等作為IO事件的采集器
- Dispatcher 提供注冊(cè)/刪除事件并進(jìn)行分發(fā),作為事件分發(fā)器
- Event Handler 事件處理器 完成具體事件的回調(diào) 供Dispatcher調(diào)用
- Concrete Event Handler 具體請(qǐng)求處理函數(shù)
更簡(jiǎn)潔的流程如下:
以網(wǎng)絡(luò)場(chǎng)景為例:
循環(huán)前先將待監(jiān)控的事件進(jìn)行注冊(cè),當(dāng)監(jiān)控中的Socket讀寫(xiě)事件到來(lái)時(shí),事件采集器epoll等IO復(fù)用工具檢測(cè)到并且將事件返回給事件分發(fā)器Dispatcher,分發(fā)器根據(jù)讀、寫(xiě)、異常等情況進(jìn)行分發(fā)給事件處理器,事件處理器進(jìn)而根據(jù)事件具體類(lèi)型來(lái)調(diào)度相應(yīng)的實(shí)現(xiàn)函數(shù)來(lái)完成任務(wù)。
4. Redis的Reactor實(shí)現(xiàn)
Redis處理客戶(hù)端業(yè)務(wù)(文件事件)的基本流程:
- Redis的IO復(fù)用的選擇
Redis中支持多種IO復(fù)用,源碼中使用相應(yīng)的宏定義進(jìn)行選擇,編譯時(shí)就可以獲取當(dāng)前系統(tǒng)支持的最優(yōu)的IO復(fù)用函數(shù)來(lái)使用,從而實(shí)現(xiàn)了Redis的優(yōu)秀的可移植特性。
- Redis的任務(wù)事件隊(duì)列
由于Redis的是單線程處理業(yè)務(wù)的,因此IO復(fù)用程序?qū)⒆x寫(xiě)事件同步的逐一放入隊(duì)列中,如果當(dāng)前隊(duì)列已經(jīng)滿(mǎn)了,那么只能出一個(gè)入一個(gè),但是由于Redis正常情況下處理得很快,不太會(huì)出現(xiàn)隊(duì)列滿(mǎn)遲遲無(wú)法放任務(wù)的情況,但是當(dāng)執(zhí)行某些阻塞操作時(shí)將導(dǎo)致長(zhǎng)時(shí)間的阻塞,無(wú)法處理新任務(wù)。
- Redis事件分派器
事件的可讀寫(xiě)是從服務(wù)器角度看的,分派看到的事件類(lèi)型包括:
- AE_READABLE 客戶(hù)端寫(xiě)數(shù)據(jù)、關(guān)閉連接、新連接到達(dá)
- AE_WRITEABLE 客戶(hù)端讀數(shù)據(jù)
特別地,當(dāng)一個(gè)套接字連接同時(shí)可讀可寫(xiě)時(shí),服務(wù)器會(huì)優(yōu)先處理讀事件再處理寫(xiě)事件,也就是讀優(yōu)先。
- Redis事件處理器
Redis將文件事件進(jìn)行歸類(lèi),編寫(xiě)了多個(gè)事件處理器函數(shù),其中包括:
- 連接應(yīng)答處理器:實(shí)現(xiàn)新連接的建立
- 命令請(qǐng)求處理器:處理客戶(hù)端的新命令
- 命令回復(fù)處理器:返回客戶(hù)端的請(qǐng)求結(jié)果
- 復(fù)制處理器:實(shí)現(xiàn)主從服務(wù)器的數(shù)據(jù)復(fù)制
當(dāng)然還有其他的事件處理函數(shù),但是只要的是這四種。
- Redis C/S一次完整的交互
Redis服務(wù)器的主線程處于循環(huán)中,此時(shí)一個(gè)Client向Redis服務(wù)器發(fā)起連接請(qǐng)求,假如是6379端口,監(jiān)聽(tīng)端口在IO復(fù)用工具下檢測(cè)到AE_READABLE事件,并將該事件放入TaskQueue中,等待被處理,事件分派器獲取這個(gè)讀事件,進(jìn)一步確定是新連接請(qǐng)求,就將該事件交給了連接應(yīng)答處理器建立連接;建立連接之后Client繼續(xù)向服務(wù)器發(fā)送了一個(gè)get命令,仍然被IO復(fù)用檢測(cè)處理放入隊(duì)列,被事件分派器處理指派給命令請(qǐng)求處理器,調(diào)用相應(yīng)程序進(jìn)行執(zhí)行;服務(wù)器將套接字的AE_WRITEABLE事件與命令回復(fù)處理器相關(guān)聯(lián),當(dāng)客戶(hù)端嘗試讀取結(jié)果時(shí)產(chǎn)生可寫(xiě)事件,此時(shí)服務(wù)器端觸發(fā)命令回復(fù)響應(yīng),并將數(shù)據(jù)結(jié)果寫(xiě)入套接字,完成之后服務(wù)端接觸該套接字與命令回復(fù)處理器之間的關(guān)聯(lián);
5.參考資料
Reactor反應(yīng)器模式 (epoll)?www.cnblogs.com深入理解Reactor模式 | 獨(dú)木の白帆?www.s0nnet.com高性能網(wǎng)絡(luò)編程6--reactor反應(yīng)堆與定時(shí)器管理 - 云+社區(qū) - 騰訊云?cloud.tencent.comJava NIO淺析?tech.meituan.com6.往期精彩
靜海聽(tīng)風(fēng):Linux中的各種鎖及其基本原理?zhuanlan.zhihu.com靜海聽(tīng)風(fēng):淺析Redis 4.0新特性之LazyFree?zhuanlan.zhihu.com靜海聽(tīng)風(fēng):理解Redis持久化?zhuanlan.zhihu.com靜海聽(tīng)風(fēng):深入理解IO復(fù)用之epoll?zhuanlan.zhihu.com靜海聽(tīng)風(fēng):淺析CPython的全局解釋鎖GIL?zhuanlan.zhihu.com靜海聽(tīng)風(fēng):淺談Linux下Socket選項(xiàng)設(shè)置?zhuanlan.zhihu.com總結(jié)
以上是生活随笔為你收集整理的curl 请求没反应_理解Redis的反应堆模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 猪肚鸡火锅的做法(猪肚鸡火锅配菜哪些好)
- 下一篇: MMORPG游戏开发入门(转)