Redis的事件

前言:Redis服務(wù)器是一個(gè)事件驅(qū)動(dòng)程序跛十,服務(wù)器需要處理兩種事件:

1卑硫、文件事件:Redis服務(wù)器通過套接字和客戶端進(jìn)行鏈接觉增,而文件事件就是服務(wù)器對套接字操作的抽象奠货。服務(wù)端和客戶端之間的通信會(huì)產(chǎn)生相應(yīng)的文件事件堕担,而服務(wù)器則通過監(jiān)聽并處理這些事件來完成一系列網(wǎng)絡(luò)通信操作已慢。

2、時(shí)間事件:Redis服務(wù)器中的一些操作霹购,比如serverCron函數(shù)需要在給定的時(shí)間點(diǎn)執(zhí)行佑惠,而時(shí)間事件就是服務(wù)器對這類定時(shí)操作的抽象。


1齐疙、文件事件

? ? redis基于Reactor模式開發(fā)了自己的網(wǎng)絡(luò)事件處理器:這個(gè)處理器被稱為文件事件處理器膜楷。

? ? 1、文件事件處理器使用I/O多路復(fù)用程序來同時(shí)監(jiān)聽多個(gè)套接字贞奋,并根據(jù)套接字目前執(zhí)行的任務(wù)來為套接字關(guān)聯(lián)不同的事件處理器赌厅。

? ? 2、當(dāng)被監(jiān)聽的套接字準(zhǔn)備好執(zhí)行連接應(yīng)答(accept)轿塔、讀忍卦浮(read)仲墨、寫入(write)、關(guān)閉(close)等操作時(shí)揍障,與操作相對應(yīng)的文件事件就會(huì)產(chǎn)生目养,這時(shí)文件事件處理器就會(huì)調(diào)用套接字之前關(guān)聯(lián)好的事件處理器來處理這些事件。

? ? 雖然文件事件處理器以單線程方式進(jìn)行毒嫡,但通過使用I/O多路復(fù)用程序來監(jiān)聽多個(gè)套接字癌蚁,文件事件處理器既實(shí)現(xiàn)了高性能的網(wǎng)絡(luò)通信模型,又可以很好地與redis服務(wù)器中其他同樣以單線程模式方式運(yùn)行的模塊進(jìn)行對接兜畸,這保持了redis內(nèi)部單線程設(shè)計(jì)的簡單性努释。


1.1、文件事件處理器的構(gòu)成


? ? 文件事件處理器包括四個(gè)部分:套接字咬摇、I/O多路復(fù)用程序洽洁,文件事件分派器,事件處理器菲嘴。

? ? 文件事件是對套接字的抽象,每當(dāng)一個(gè)套接字準(zhǔn)備好執(zhí)行連接應(yīng)答(accept)汰翠、寫入龄坪、讀取、關(guān)閉等操作時(shí)复唤,就會(huì)產(chǎn)生一個(gè)文件事件健田。因?yàn)橐粋€(gè)服務(wù)器通常會(huì)連接多個(gè)套接字,所以多個(gè)文件事件有可能并發(fā)的出現(xiàn)佛纫。

? ? I/O多路復(fù)用程序負(fù)責(zé)監(jiān)聽多個(gè)套接字妓局,并向文件時(shí)間分派器傳送那些產(chǎn)生了事件的套接字。

? ? 盡管多個(gè)文件事件可能會(huì)并發(fā)的出現(xiàn)呈宇,但I/O多路復(fù)用程序總是會(huì)將所有產(chǎn)生事件的套接字都放到一個(gè)隊(duì)列里面好爬,然后通過這個(gè)隊(duì)列,?以有序(sequentially)甥啄、同步(synchronously)存炮、每次一個(gè)套接字的方式向文件事件分派器傳送套接字: 當(dāng)上一個(gè)套接字產(chǎn)生的事件被處理完畢之后(該套接字為事件所關(guān)聯(lián)的事件處理器執(zhí)行完畢), I/O 多路復(fù)用程序才會(huì)繼續(xù)向文件事件分派器傳送下一個(gè)套接字蜈漓。


? ? 文件事件分配器接受I/O多路復(fù)用程序傳來的套接字穆桂,并根據(jù)套接字產(chǎn)生的事件類型調(diào)用相應(yīng)的事件處理器融虽。

? ? 服務(wù)器會(huì)為執(zhí)行不同任務(wù)的套接字關(guān)聯(lián)不同的事件處理器享完,這些處理器是一個(gè)個(gè)函數(shù),它們定義了某個(gè)事件發(fā)生時(shí)有额,服務(wù)器應(yīng)該執(zhí)行的動(dòng)作般又。


1.2彼绷、I/O多路復(fù)用程序的實(shí)現(xiàn)

? ??Redis 的 I/O 多路復(fù)用程序的所有功能都是通過包裝常見的?select?、?epoll?倒源、?evport?和?kqueue?這些 I/O 多路復(fù)用函數(shù)庫來實(shí)現(xiàn)的苛预, 每個(gè) I/O 多路復(fù)用函數(shù)庫在 Redis 源碼中都對應(yīng)一個(gè)單獨(dú)的文件, 比如?ae_select.c?笋熬、?ae_epoll.c?热某、?ae_kqueue.c?, 諸如此類胳螟。


? ??Redis 在 I/O 多路復(fù)用程序的實(shí)現(xiàn)源碼中用?#include?宏定義了相應(yīng)的規(guī)則昔馋, 程序會(huì)在編譯時(shí)自動(dòng)選擇系統(tǒng)中性能最高的 I/O 多路復(fù)用函數(shù)庫來作為 Redis 的 I/O 多路復(fù)用程序的底層實(shí)現(xiàn)。


1.3糖耸、事件的類型

????I/O 多路復(fù)用程序可以監(jiān)聽多個(gè)套接字的?ae.h/AE_READABLE?事件和?ae.h/AE_WRITABLE?事件秘遏, 這兩類事件和套接字操作之間的對應(yīng)關(guān)系如下:

? ? 1、當(dāng)套接字變得可讀時(shí)(客戶端對套接字執(zhí)行?write?操作嘉竟,或者執(zhí)行?close?操作)邦危, 或者有新的可應(yīng)答(acceptable)套接字出現(xiàn)時(shí)(客戶端對服務(wù)器的監(jiān)聽套接字執(zhí)行?connect?操作), 套接字產(chǎn)生?AE_READABLE?事件舍扰。

? ? 2倦蚪、當(dāng)套接字變得可寫時(shí)(客戶端對套接字執(zhí)行?read?操作), 套接字產(chǎn)生?AE_WRITABLE?事件边苹。

????I/O 多路復(fù)用程序允許服務(wù)器同時(shí)監(jiān)聽套接字的?AE_READABLE?事件和?AE_WRITABLE?事件陵且, 如果一個(gè)套接字同時(shí)產(chǎn)生了這兩種事件, 那么文件事件分派器會(huì)優(yōu)先處理?AE_READABLE?事件个束, 等到?AE_READABLE?事件處理完之后慕购, 才處理?AE_WRITABLE?事件。這也就是說茬底, 如果一個(gè)套接字又可讀又可寫的話沪悲, 那么服務(wù)器將先讀套接字, 后寫套接字阱表。


1.4可训、文件事件處理器

? ??Redis 為文件事件編寫了多個(gè)處理器, 這些事件處理器分別用于實(shí)現(xiàn)不同的網(wǎng)絡(luò)通訊需求捶枢, 比如說:

? ? 1握截、為了對連接服務(wù)器的各個(gè)客戶端進(jìn)行應(yīng)答, 服務(wù)器要為監(jiān)聽套接字關(guān)聯(lián)連接應(yīng)答處理器烂叔。

? ? 2谨胞、為了接收客戶端傳來的命令請求, 服務(wù)器要為客戶端套接字關(guān)聯(lián)命令請求處理器蒜鸡。

? ? 3胯努、為了向客戶端返回命令的執(zhí)行結(jié)果牢裳, 服務(wù)器要為客戶端套接字關(guān)聯(lián)命令回復(fù)處理器。

????在這些事件處理器里面叶沛, 服務(wù)器最常用的要數(shù)與客戶端進(jìn)行通信的連接應(yīng)答處理器蒲讯、 命令請求處理器和命令回復(fù)處理器

? ? ? ??

連接應(yīng)答處理器



命令請求處理器


命令回復(fù)處理器


2、時(shí)間事件

? ? redis的時(shí)間事件可以分為兩類:

? ? 1灰署、定時(shí)事件:讓一段程序在指定的時(shí)間之后執(zhí)行一次判帮。

? ? 2、周期性事件:讓一段代碼每隔制定事件就執(zhí)行一次溉箕。


? ? 一個(gè)事件事件主要由一下三個(gè)屬性組成:

? ? 1晦墙、id:服務(wù)器為時(shí)間事件創(chuàng)建的全局唯一ID。ID從小到大遞增肴茄,新事件的ID要比舊事件的ID大晌畅。

? ? 2、when:毫秒時(shí)間戳寡痰,記錄時(shí)間事件的到達(dá)時(shí)間抗楔。

? ? 3、timeproc:時(shí)間事件處理器 拦坠,一個(gè)函數(shù)连躏。當(dāng)時(shí)間事件到達(dá)時(shí),服務(wù)器就會(huì)調(diào)用相應(yīng)的處理器來處理事件贪婉。


? ? 一個(gè)時(shí)間事件是定時(shí)事件還是周期性事件取決于時(shí)間事件處理器的返回值。

? ? 1卢肃、如果返回值是ae.h/AE_NOMORE疲迂,那么是定時(shí)事件,表示只執(zhí)行一次莫湘,執(zhí)行完就會(huì)被刪除尤蒿。

? ? 2、如果返回值不是ae.h/AE_NOMORE幅垮,那么是周期性事件:當(dāng)一個(gè)時(shí)間事件到達(dá)之后腰池,服務(wù)器會(huì)根據(jù)時(shí)間事件處理器的返回值,對時(shí)間事件的when屬性進(jìn)行更新忙芒,讓這個(gè)時(shí)間可以在一段事件后再次到達(dá)示弓。比如,返回30呵萨,那么服務(wù)器就會(huì)對這個(gè)時(shí)間時(shí)間的when更新奏属,30ms之后讓這個(gè)事件再次到達(dá)。? ? ?

? ? 目前潮峦,redis只支持了周期性事件囱皿,并為支持定時(shí)事件勇婴。


2.1、實(shí)現(xiàn)? ??



? ? 服務(wù)器將所有的時(shí)間事件都放在一個(gè)無序鏈表中嘱腥,每當(dāng)時(shí)間事件執(zhí)行器運(yùn)行時(shí)耕渴,它就遍歷整個(gè)鏈表,查找所有已到達(dá)的時(shí)間事件齿兔,并調(diào)用相應(yīng)的事件處理器橱脸。

? ? 新生成的事件ID都是較大的,他們總是會(huì)被插入到鏈表的表頭 愧驱,事件一般都是逆序排序的慰技。

? ? 注意:我們說保存時(shí)間事件的鏈表是無序鏈表,指的不是鏈表沒有按ID排序组砚,而是指吻商,該鏈表不按when排序。正因?yàn)闆]有按when排序糟红,所以當(dāng)時(shí)間事件執(zhí)行器運(yùn)行的時(shí)候艾帐,它必須遍歷鏈表中所有的時(shí)間事件,這樣才能確保服務(wù)器中所有已經(jīng)到達(dá)的時(shí)間事件都會(huì)被處理盆偿。

? ? 其實(shí)柒爸,無序鏈表不影響時(shí)間事件處理器的性能,因?yàn)檫@個(gè)鏈表中事扭,目前只有一個(gè)serverCron時(shí)間事件捎稚。


2.2、serverCron函數(shù)? ??

????持續(xù)運(yùn)行的redis服務(wù)器需要定期對自身的資源和狀態(tài)進(jìn)行檢查和調(diào)整求橄,從而確保服務(wù)器可以長期今野、穩(wěn)定的運(yùn)行下去,這些操作都由serverCron函數(shù)來負(fù)責(zé)執(zhí)行罐农。包括:

????1条霜、更新服務(wù)器的各類統(tǒng)計(jì)信息,比如時(shí)間涵亏、內(nèi)存占用宰睡、數(shù)據(jù)庫占用情況。

? ? 2气筋、清理數(shù)據(jù)庫的過期鍵(定期刪除)

? ? 3拆内、關(guān)閉和清理失敗的客戶端

? ? 4、嘗試進(jìn)行AOF或RDB持久化操作

? ? 5宠默、如果是主服務(wù)器矛纹,那么對從服務(wù)器進(jìn)行定期同步

? ? 6、如果是集群模式光稼,對集群進(jìn)行定期同步和連接測試

? ??

? ? redis2.6以前 或南,服務(wù)器默認(rèn)規(guī)定每秒執(zhí)行10次孩等,100ms一次。

? ? redis2.8以后采够,配置文件hz選項(xiàng)可配置肄方。


3、時(shí)間的調(diào)度與執(zhí)行

? ? 因?yàn)榉?wù)器同時(shí)存在文件事件和時(shí)間事件兩種 事件類型蹬癌,所以服務(wù)器必須對這兩種事件進(jìn)行調(diào)度权她,決定何時(shí)執(zhí)行時(shí)間事件,何時(shí)執(zhí)行文件事件逝薪,以及花多少事件來處理他們隅要。

1.aeApiPoll函數(shù)的最大阻塞時(shí)間是由到達(dá)時(shí)間最接近當(dāng)前時(shí)間的時(shí)間事件決定,這個(gè)方法既可以避免服務(wù)器對時(shí)間事件進(jìn)行頻繁的輪詢(忙等待)董济,也可以確保aeApiPoll函數(shù)不會(huì)阻塞過長時(shí)間步清。? ??

2.因?yàn)槲募录请S機(jī)出現(xiàn)的,如果等待并處理完一次文件事件之后虏肾,仍未有任何時(shí)間事件到達(dá)廓啊,那么服務(wù)器將再次等待并處理文件事件。隨著文件事件的不斷執(zhí)行封豪,時(shí)間會(huì)逐漸向時(shí)間事件所設(shè)置的到達(dá)時(shí)間逼近谴轮,并最終來到到達(dá)事件,這時(shí)服務(wù)器就可以開始處理到達(dá)的時(shí)間事件了吹埠。

3.對文件事件和時(shí)間事件的處理都是同步第步,有序,原子地執(zhí)行的缘琅,服務(wù)器不會(huì)中途中斷事件處理粘都,也不會(huì)對事件進(jìn)行搶占,因此胯杭,不管是文件事件的處理器驯杜,還是時(shí)間事件的處理器受啥,它們都會(huì)盡可能地減少程序的阻塞事件做个,并在有需要時(shí)主動(dòng)讓出執(zhí)行權(quán),從而降低造成事件饑餓的可能性滚局。比如說居暖,再命令回復(fù)處理器將一個(gè)命令回復(fù)寫入到客戶端套接字時(shí),如果寫入字節(jié)數(shù)超過了一個(gè)預(yù)設(shè)常量的話藤肢,命令回復(fù)處理器就會(huì)主動(dòng)用break跳出寫入循環(huán)太闺,將余下的數(shù)據(jù)留到下次再寫;另外嘁圈,時(shí)間事件也會(huì)將非常耗時(shí)的持久化操作放到子線程或者子進(jìn)程執(zhí)行省骂。

4.因?yàn)闀r(shí)間事件在文件事件之后執(zhí)行蟀淮,并且事件之間不會(huì)出現(xiàn)搶占,所以時(shí)間事件的實(shí)際處理時(shí)間钞澳,通常會(huì)比時(shí)間事件設(shè)定的到達(dá)時(shí)間稍微晚一些怠惶。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市轧粟,隨后出現(xiàn)的幾起案子策治,更是在濱河造成了極大的恐慌,老刑警劉巖兰吟,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件通惫,死亡現(xiàn)場離奇詭異,居然都是意外死亡混蔼,警方通過查閱死者的電腦和手機(jī)履腋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拄丰,“玉大人府树,你說我怎么就攤上這事×习矗” “怎么了奄侠?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長载矿。 經(jīng)常有香客問我垄潮,道長,這世上最難降的妖魔是什么闷盔? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任弯洗,我火速辦了婚禮,結(jié)果婚禮上逢勾,老公的妹妹穿的比我還像新娘牡整。我一直安慰自己,他們只是感情好溺拱,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布逃贝。 她就那樣靜靜地躺著,像睡著了一般迫摔。 火紅的嫁衣襯著肌膚如雪沐扳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天句占,我揣著相機(jī)與錄音沪摄,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛杨拐,可吹牛的內(nèi)容都是我干的祈餐。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼哄陶,長吁一口氣:“原來是場噩夢啊……” “哼昼弟!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起奕筐,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤舱痘,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后离赫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芭逝,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年渊胸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了旬盯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡翎猛,死狀恐怖胖翰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情切厘,我是刑警寧澤萨咳,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站疫稿,受9級特大地震影響培他,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜遗座,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一舀凛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧途蒋,春花似錦猛遍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至筋帖,卻和暖如春奸晴,著一層夾襖步出監(jiān)牢的瞬間冤馏,已是汗流浹背日麸。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人代箭。 一個(gè)月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓墩划,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嗡综。 傳聞我的和親對象是個(gè)殘疾皇子乙帮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360