redis設(shè)計(jì)與實(shí)現(xiàn)-事件

事件

事件是 Redis 服務(wù)器的核心, 它處理兩項(xiàng)重要的任務(wù):

文件事件(file event):在多個(gè)客戶端中實(shí)現(xiàn)多路復(fù)用,接受它們發(fā)來的命令請(qǐng)求,并將命令的執(zhí)行結(jié)果>返回給客戶端。
時(shí)間事件(time event):實(shí)現(xiàn)服務(wù)器常規(guī)操作(server cron job)研铆。

文件事件

Redis 服務(wù)器通過在多個(gè)客戶端之間進(jìn)行多路復(fù)用, 從而實(shí)現(xiàn)高效的命令請(qǐng)求處理: 多個(gè)客戶端通過套接字連接到 Redis 服務(wù)器中州叠, 但只有在套接字可以無阻塞地進(jìn)行讀或者寫時(shí)棵红, 服務(wù)器才會(huì)和這些客戶端進(jìn)行交互。

Redis 將這類因?yàn)閷?duì)套接字進(jìn)行多路復(fù)用而產(chǎn)生的事件稱為文件事件(file event)咧栗, 文件事件可以分為讀事件和寫事件兩類逆甜。

多路復(fù)用產(chǎn)生的套接字都放到一個(gè)隊(duì)列中。以有序致板,同步方式向文件事件分派器發(fā)送套接字

讀事件

讀事件標(biāo)志著客戶端命令請(qǐng)求的發(fā)送狀態(tài)交煞。

當(dāng)一個(gè)新的客戶端連接到服務(wù)器時(shí), 服務(wù)器會(huì)給為該客戶端綁定讀事件斟或, 直到客戶端斷開連接之后素征, 這個(gè)讀事件才會(huì)被移除。

讀事件在整個(gè)網(wǎng)絡(luò)連接的生命期內(nèi)萝挤, 都會(huì)在等待和就緒兩種狀態(tài)之間切換:

當(dāng)客戶端只是連接到服務(wù)器御毅,但并沒有向服務(wù)器發(fā)送命令時(shí),該客戶端的讀事件就處于等待狀態(tài)怜珍。
當(dāng)客戶端給服務(wù)器發(fā)送命令請(qǐng)求端蛆,并且請(qǐng)求已到達(dá)時(shí)(相應(yīng)的套接字可以無阻塞地執(zhí)行讀操作),該客戶端的讀事件處于就緒狀態(tài)绘面。
當(dāng)事件處理器被執(zhí)行時(shí)欺税, 就緒的文件事件會(huì)被識(shí)別到侈沪, 相應(yīng)的命令請(qǐng)求會(huì)被發(fā)送到命令執(zhí)行器揭璃, 并對(duì)命令進(jìn)行求值。

寫事件

寫事件標(biāo)志著客戶端對(duì)命令結(jié)果的接收狀態(tài)亭罪。

和客戶端自始至終都關(guān)聯(lián)著讀事件不同瘦馍, 服務(wù)器只會(huì)在有命令結(jié)果要傳回給客戶端時(shí), 才會(huì)為客戶端關(guān)聯(lián)寫事件应役, 并且在命令結(jié)果傳送完畢之后情组, 客戶端和寫事件的關(guān)聯(lián)就會(huì)被移除。

一個(gè)寫事件會(huì)在兩種狀態(tài)之間切換:

當(dāng)服務(wù)器有命令結(jié)果需要返回給客戶端箩祥,但客戶端還未能執(zhí)行無阻塞寫院崇,那么寫事件處于等待狀態(tài)。
當(dāng)服務(wù)器有命令結(jié)果需要返回給客戶端袍祖,并且客戶端可以進(jìn)行無阻塞寫底瓣,那么寫事件處于就緒狀態(tài)。
當(dāng)客戶端向服務(wù)器發(fā)送命令請(qǐng)求蕉陋, 并且請(qǐng)求被接受并執(zhí)行之后捐凭, 服務(wù)器就需要將保存在緩存內(nèi)的命令執(zhí)行結(jié)果返回給客戶端拨扶, 這時(shí)服務(wù)器就會(huì)為客戶端關(guān)聯(lián)寫事件。

同時(shí)關(guān)聯(lián)寫事件和讀事件
前面提到過茁肠,讀事件只有在客戶端斷開和服務(wù)器的連接時(shí)患民,才會(huì)被移除。

這也就是說垦梆,當(dāng)客戶端關(guān)聯(lián)寫事件的時(shí)候匹颤,實(shí)際上它在同時(shí)關(guān)聯(lián)讀/寫兩種事件。

因?yàn)樵谕淮挝募录幚砥鞯恼{(diào)用中托猩, 單個(gè)客戶端只能執(zhí)行其中一種事件(要么讀惋嚎,要么寫,但不能又讀又寫)站刑, 當(dāng)出現(xiàn)讀事件和寫事件同時(shí)就緒的情況時(shí)另伍, 事件處理器優(yōu)先處理讀事件。這也就是說绞旅, 當(dāng)服務(wù)器有命令結(jié)果要返回客戶端摆尝, 而客戶端又有新命令請(qǐng)求進(jìn)入時(shí), 服務(wù)器先處理新命令請(qǐng)求因悲。

時(shí)間事件

時(shí)間事件記錄著那些要在指定時(shí)間點(diǎn)運(yùn)行的事件堕汞, 多個(gè)時(shí)間事件以無序鏈表的形式保存在服務(wù)器狀態(tài)中。

redis時(shí)間事件分為2類:

定時(shí)事件:在指定時(shí)間之后晃琳,執(zhí)行一次讯检。
周期性事件:每隔一段時(shí)間就執(zhí)行一次。
每個(gè)時(shí)間事件主要由以下幾個(gè)屬性組成:

id:全局唯一ID卫旱,新事件ID號(hào)比舊事件ID號(hào)大人灼。
when :以毫秒格式的 UNIX 時(shí)間戳為單位,記錄了應(yīng)該在什么時(shí)間點(diǎn)執(zhí)行事件處理函數(shù)顾翼。
timeProc :事件處理函數(shù)投放。
next 指向下一個(gè)時(shí)間事件,形成鏈表适贸。
根據(jù) timeProc 函數(shù)的返回值灸芳,可以將時(shí)間事件劃分為兩類:

如果事件處理函數(shù)返回 ae.h/AE_NOMORE ,那么這個(gè)事件為單次執(zhí)行事件:該事件會(huì)在指定的時(shí)間被處理一次拜姿,之后該事件就會(huì)被刪除烙样,不再執(zhí)行。
如果事件處理函數(shù)返回一個(gè)非 AE_NOMORE 的整數(shù)值蕊肥,那么這個(gè)事件為循環(huán)執(zhí)行事件:該事件會(huì)在指定的時(shí)間被處理谒获,之后它會(huì)按照事件處理函數(shù)的返回值,更新事件的 when 屬性,讓這個(gè)事件在之后的某個(gè)時(shí)間點(diǎn)再次運(yùn)行究反,并以這種方式一直更新并運(yùn)行下去寻定。
實(shí)現(xiàn)
服務(wù)器將所有時(shí)間事件都放在一個(gè)無序列表中,每當(dāng)時(shí)間事件執(zhí)行器運(yùn)行時(shí)精耐,就遍歷列表狼速,查找所有已到達(dá)時(shí)間事件,并調(diào)用相應(yīng)事件處理器卦停。無序列表不是指不按ID排序向胡,是指不按when排序。

無序鏈表并不影響時(shí)間事件處理器的性能

在目前的版本中惊完, 正常模式下的 Redis 只帶有 serverCron 一個(gè)時(shí)間事件僵芹, 而在 benchmark 模式下, Redis 也只使用兩個(gè)時(shí)間事件小槐。

在這種情況下拇派, 程序幾乎是將無序鏈表退化成一個(gè)指針來使用, 所以使用無序鏈表來保存時(shí)間事件凿跳, 并不影響事件處理器的性能件豌。

服務(wù)器常規(guī)操作
對(duì)于持續(xù)運(yùn)行的服務(wù)器來說, 服務(wù)器需要定期對(duì)自身的資源和狀態(tài)進(jìn)行必要的檢查和整理控嗜, 從而讓服務(wù)器維持在一個(gè)健康穩(wěn)定的狀態(tài)茧彤, 這類操作被統(tǒng)稱為常規(guī)操作(cron job)。

在 Redis 中疆栏, 常規(guī)操作由 redis.c/serverCron 實(shí)現(xiàn)曾掂, 它主要執(zhí)行以下操作:

更新服務(wù)器的各類統(tǒng)計(jì)信息,比如時(shí)間壁顶、內(nèi)存占用珠洗、數(shù)據(jù)庫占用情況等。
清理數(shù)據(jù)庫中的過期鍵值對(duì)博助。
對(duì)不合理的數(shù)據(jù)庫進(jìn)行大小調(diào)整险污。
關(guān)閉和清理連接失效的客戶端。
嘗試進(jìn)行 AOF 或 RDB 持久化操作富岳。
如果服務(wù)器是主節(jié)點(diǎn)的話,對(duì)附屬節(jié)點(diǎn)進(jìn)行定期同步拯腮。
如果處于集群模式的話窖式,對(duì)集群進(jìn)行定期同步和連接測(cè)試。
Redis 將 serverCron 作為時(shí)間事件來運(yùn)行动壤, 從而確保它每隔一段時(shí)間就會(huì)自動(dòng)運(yùn)行一次萝喘, 又因?yàn)?serverCron 需要在 Redis 服務(wù)器運(yùn)行期間一直定期運(yùn)行, 所以它是一個(gè)循環(huán)時(shí)間事件: serverCron 會(huì)一直定期執(zhí)行,直到服務(wù)器關(guān)閉為止阁簸。

在 Redis 2.6 版本中爬早, 程序規(guī)定 serverCron 每秒運(yùn)行 10 次, 平均每 100 毫秒運(yùn)行一次启妹。 從 Redis 2.8 開始筛严, 用戶可以通過修改 hz 選項(xiàng)來調(diào)整 serverCron 的每秒執(zhí)行次數(shù), 具體信息請(qǐng)參考 redis.conf 文件中關(guān)于 hz 選項(xiàng)的說明饶米。

事件的執(zhí)行與調(diào)度
既然 Redis 里面既有文件事件桨啃, 又有時(shí)間事件, 那么如何調(diào)度這兩種事件就成了一個(gè)關(guān)鍵問題檬输。

簡單地說照瘾, Redis 里面的兩種事件呈合作關(guān)系, 它們之間包含以下三種屬性:

一種事件會(huì)等待另一種事件執(zhí)行完畢之后丧慈,才開始執(zhí)行析命,事件之間不會(huì)出現(xiàn)搶占。
事件處理器先處理文件事件(處理命令請(qǐng)求)逃默,再執(zhí)行時(shí)間事件(調(diào)用 serverCron)
文件事件的等待時(shí)間(類 poll 函數(shù)的最大阻塞時(shí)間)碳却,由距離到達(dá)時(shí)間最短的時(shí)間事件決定。
這些屬性表明笑旺, 實(shí)際處理時(shí)間事件的時(shí)間昼浦, 通常會(huì)比時(shí)間事件所預(yù)定的時(shí)間要晚, 至于延遲的時(shí)間有多長筒主, 取決于時(shí)間事件執(zhí)行之前关噪, 執(zhí)行文件事件所消耗的時(shí)間。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乌妙,一起剝皮案震驚了整個(gè)濱河市使兔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌藤韵,老刑警劉巖虐沥,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異泽艘,居然都是意外死亡欲险,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門匹涮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來天试,“玉大人,你說我怎么就攤上這事然低∠裁浚” “怎么了务唐?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長带兜。 經(jīng)常有香客問我枫笛,道長,這世上最難降的妖魔是什么刚照? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任刑巧,我火速辦了婚禮,結(jié)果婚禮上涩咖,老公的妹妹穿的比我還像新娘海诲。我一直安慰自己,他們只是感情好檩互,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布特幔。 她就那樣靜靜地躺著,像睡著了一般闸昨。 火紅的嫁衣襯著肌膚如雪蚯斯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天饵较,我揣著相機(jī)與錄音拍嵌,去河邊找鬼。 笑死循诉,一個(gè)胖子當(dāng)著我的面吹牛横辆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播茄猫,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼狈蚤,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了划纽?” 一聲冷哼從身側(cè)響起脆侮,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎勇劣,沒想到半個(gè)月后靖避,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡比默,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年幻捏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片退敦。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡粘咖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出侈百,到底是詐尸還是另有隱情瓮下,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布钝域,位于F島的核電站讽坏,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏例证。R本人自食惡果不足惜路呜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望织咧。 院中可真熱鬧胀葱,春花似錦、人聲如沸笙蒙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捅位。三九已至轧葛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間艇搀,已是汗流浹背尿扯。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留焰雕,地道東北人衷笋。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像矩屁,于是被迫代替她去往敵國和親辟宗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

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