校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > Redis中事件驅動模型示例詳解

Redis中事件驅動模型示例詳解

熱門標簽:太原營銷外呼系統 最簡單的百度地圖標注 百度商家地圖標注怎么做 西藏教育智能外呼系統價格 玄武湖地圖標注 小紅書怎么地圖標注店 竹間科技AI電銷機器人 地圖標注費用 地圖標注如何即時生效

前言

Redis 是一個事件驅動的內存數據庫,服務器需要處理兩種類型的事件。

  • 文件事件
  • 時間事件

下面就會介紹這兩種事件的實現原理。

文件事件

Redis 服務器通過 socket 實現與客戶端(或其他redis服務器)的交互,文件事件就是服務器對 socket 操作的抽象。 Redis 服務器,通過監聽這些 socket 產生的文件事件并處理這些事件,實現對客戶端調用的響應。

Reactor

Redis 基于 Reactor 模式開發了自己的事件處理器。

這里就先展開講一講 Reactor 模式??聪聢D:

“I/O 多路復用模塊”會監聽多個 FD ,當這些FD產生,accept,read,write 或 close 的文件事件。會向“文件事件分發器(dispatcher)”傳送事件。

文件事件分發器(dispatcher)在收到事件之后,會根據事件的類型將事件分發給對應的 handler。

我們順著圖,從上到下的逐一講解 Redis 是怎么實現這個 Reactor 模型的。

I/O 多路復用模塊

Redis 的 I/O 多路復用模塊,其實是封裝了操作系統提供的 select,epoll,avport 和 kqueue 這些基礎函數。向上層提供了一個統一的接口,屏蔽了底層實現的細節。

一般而言 Redis 都是部署到 Linux 系統上,所以我們就看看使用 Redis 是怎么利用 linux 提供的 epoll 實現I/O 多路復用。

首先看看 epoll 提供的三個方法:

/*
 * 創建一個epoll的句柄,size用來告訴內核這個監聽的數目一共有多大
 */
int epoll_create(int size);

/*
 * 可以理解為,增刪改 fd 需要監聽的事件
 * epfd 是 epoll_create() 創建的句柄。
 * op 表示 增刪改
 * epoll_event 表示需要監聽的事件,Redis 只用到了可讀,可寫,錯誤,掛斷 四個狀態
 */
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

/*
 * 可以理解為查詢符合條件的事件
 * epfd 是 epoll_create() 創建的句柄。
 * epoll_event 用來存放從內核得到事件的集合
 * maxevents 獲取的最大事件數
 * timeout 等待超時時間
 */
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

再看 Redis 對文件事件,封裝epoll向上提供的接口:

/*
 * 事件狀態
 */
typedef struct aeApiState {

 // epoll_event 實例描述符
 int epfd;

 // 事件槽
 struct epoll_event *events;

} aeApiState;

/*
 * 創建一個新的 epoll 
 */
static int aeApiCreate(aeEventLoop *eventLoop)
/*
 * 調整事件槽的大小
 */
static int aeApiResize(aeEventLoop *eventLoop, int setsize)
/*
 * 釋放 epoll 實例和事件槽
 */
static void aeApiFree(aeEventLoop *eventLoop)
/*
 * 關聯給定事件到 fd
 */
static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask)
/*
 * 從 fd 中刪除給定事件
 */
static void aeApiDelEvent(aeEventLoop *eventLoop, int fd, int mask)
/*
 * 獲取可執行事件
 */
static int aeApiPoll(aeEventLoop *eventLoop, struct timeval *tvp)

所以看看這個ae_peoll.c 如何對 epoll 進行封裝的:

  • aeApiCreate() 是對 epoll.epoll_create() 的封裝。
  • aeApiAddEvent()和aeApiDelEvent() 是對 epoll.epoll_ctl()的封裝。
  • aeApiPoll() 是對 epoll_wait()的封裝。

這樣 Redis 的利用 epoll 實現的 I/O 復用器就比較清晰了。

再往上一層次我們需要看看 ea.c 是怎么封裝的?

首先需要關注的是事件處理器的數據結構:

typedef struct aeFileEvent {
 // 監聽事件類型掩碼,
 // 值可以是 AE_READABLE 或 AE_WRITABLE ,
 // 或者 AE_READABLE | AE_WRITABLE
 int mask; /* one of AE_(READABLE|WRITABLE) */
 // 讀事件處理器
 aeFileProc *rfileProc;
 // 寫事件處理器
 aeFileProc *wfileProc;
 // 多路復用庫的私有數據
 void *clientData;
} aeFileEvent;

mask 就是可以理解為事件的類型。

除了使用 ae_peoll.c 提供的方法外,ae.c 還增加 “增刪查” 的幾個 API。

  • 增:aeCreateFileEvent
  • 刪:aeDeleteFileEvent
  • 查: 查包括兩個維度 aeGetFileEvents 獲取某個 fd 的監聽類型和aeWait等待某個fd 直到超時或者達到某個狀態。

事件分發器(dispatcher)

Redis 的事件分發器 ae.c/aeProcessEvents 不但處理文件事件還處理時間事件,所以這里只貼與文件分發相關的出部分代碼,dispather 根據 mask 調用不同的事件處理器。

//從 epoll 中獲關注的事件
numevents = aeApiPoll(eventLoop, tvp);
for (j = 0; j  numevents; j++) {
 // 從已就緒數組中獲取事件
 aeFileEvent *fe = eventLoop->events[eventLoop->fired[j].fd];
 int mask = eventLoop->fired[j].mask;
 int fd = eventLoop->fired[j].fd;
 int rfired = 0;
 // 讀事件
 if (fe->mask  mask  AE_READABLE) {
  // rfired 確保讀/寫事件只能執行其中一個
  rfired = 1;
  fe->rfileProc(eventLoop,fd,fe->clientData,mask);
 }
 // 寫事件
 if (fe->mask  mask  AE_WRITABLE) {
  if (!rfired || fe->wfileProc != fe->rfileProc)
   fe->wfileProc(eventLoop,fd,fe->clientData,mask);
 }
 processed++;
}

可以看到這個分發器,根據 mask 的不同將事件分別分發給了讀事件和寫事件。

文件事件處理器的類型

Redis 有大量的事件處理器類型,我們就講解處理一個簡單命令涉及到的三個處理器:

  • acceptTcpHandler 連接應答處理器,負責處理連接相關的事件,當有client 連接到Redis的時候們就會產生 AE_READABLE 事件。引發它執行。
  • readQueryFromClinet 命令請求處理器,負責讀取通過 sokect 發送來的命令。
  • sendReplyToClient 命令回復處理器,當Redis處理完命令,就會產生 AE_WRITEABLE 事件,將數據回復給 client。

文件事件實現總結

我們按照開始給出的 Reactor 模型,從上到下講解了文件事件處理器的實現,下面將會介紹時間時間的實現。

時間事件

Reids 有很多操作需要在給定的時間點進行處理,時間事件就是對這類定時任務的抽象。

先看時間事件的數據結構:

/* Time event structure
 *
 * 時間事件結構
 */
typedef struct aeTimeEvent {
 // 時間事件的唯一標識符
 long long id; /* time event identifier. */
 // 事件的到達時間
 long when_sec; /* seconds */
 long when_ms; /* milliseconds */
 // 事件處理函數
 aeTimeProc *timeProc;
 // 事件釋放函數
 aeEventFinalizerProc *finalizerProc;
 // 多路復用庫的私有數據
 void *clientData;
 // 指向下個時間事件結構,形成鏈表
 struct aeTimeEvent *next;
} aeTimeEvent;

看見 next 我們就知道這個 aeTimeEvent 是一個鏈表結構??磮D:

注意:這是一個按照id倒序排列的鏈表,并沒有按照事件順序排序。

processTimeEvent

Redis 使用這個函數處理所有的時間事件,我們整理一下執行思路:

  • 記錄最新一次執行這個函數的時間,用于處理系統時間被修改產生的問題。
  • 遍歷鏈表找出所有 when_sec 和 when_ms 小于現在時間的事件。
  • 執行事件對應的處理函數。
  • 檢查事件類型,如果是周期事件則刷新該事件下一次的執行事件。
  • 否則從列表中刪除事件。

綜合調度器(aeProcessEvents)

綜合調度器是 Redis 統一處理所有事件的地方。我們梳理一下這個函數的簡單邏輯:

// 1. 獲取離當前時間最近的時間事件
shortest = aeSearchNearestTimer(eventLoop);

// 2. 獲取間隔時間
timeval = shortest - nowTime;

// 如果timeval 小于 0,說明已經有需要執行的時間事件了。
if(timeval  0){
 timeval = 0
}

// 3. 在 timeval 時間內,取出文件事件。
numevents = aeApiPoll(eventLoop, timeval);

// 4.根據文件事件的類型指定不同的文件處理器
if (AE_READABLE) {
 // 讀事件
 rfileProc(eventLoop,fd,fe->clientData,mask);
}
 // 寫事件
if (AE_WRITABLE) {
 wfileProc(eventLoop,fd,fe->clientData,mask);
}

以上的偽代碼就是整個 Redis 事件處理器的邏輯。

我們可以再看看誰執行了這個 aeProcessEvents:

void aeMain(aeEventLoop *eventLoop) {
 eventLoop->stop = 0;
 while (!eventLoop->stop) {
  // 如果有需要在事件處理前執行的函數,那么運行它
  if (eventLoop->beforesleep != NULL)
   eventLoop->beforesleep(eventLoop);
  // 開始處理事件
  aeProcessEvents(eventLoop, AE_ALL_EVENTS);
 }
}

然后我們再看看是誰調用了 eaMain:

int main(int argc, char **argv) {
 //一些配置和準備
 ...
 aeMain(server.el);
 
 //結束后的回收工作
 ...
}

我們在 Redis 的 main 方法中找個了它。

這個時候我們整理出的思路就是:

  • Redis 的 main() 方法執行了一些配置和準備以后就調用 eaMain() 方法。
  • eaMain() while(true) 的調用 aeProcessEvents()。

所以我們說 Redis 是一個事件驅動的程序,期間我們發現,Redis 沒有 fork 過任何線程。所以也可以說 Redis 是一個基于事件驅動的單線程應用。

總結

在后端的面試中 Redis 總是一個或多或少會問到的問題。

讀完這篇文章你也許就能回答這幾個問題:

為什么 Redis 是一個單線程應用?
為什么 Redis 是一個單線程應用,卻有如此高的性能?
如果你用本文提供的知識點回答這兩個問題,一定會在面試官心中留下一個高大的形象。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

標簽:景德鎮 澳門 香港 唐山 揚州 贛州 廣東 林芝

巨人網絡通訊聲明:本文標題《Redis中事件驅動模型示例詳解》,本文關鍵詞  Redis,中,事件,驅動,模型,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《Redis中事件驅動模型示例詳解》相關的同類信息!
  • 本頁收集關于Redis中事件驅動模型示例詳解的相關信息資訊供網民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    韩国v欧美v日本v亚洲v| 一区二区激情小说| 国产精品久久久久久久久久免费看| 久久精品在线观看| **性色生活片久久毛片| 天堂久久久久va久久久久| 韩国精品主播一区二区在线观看| av电影天堂一区二区在线观看| 国产精品羞羞答答xxdd| 国产精品中文欧美| 欧美在线观看18| 国产亚洲欧美一级| 日韩国产精品大片| 成人高清在线视频| 欧美一区二区三区色| 综合色天天鬼久久鬼色| 日本v片在线高清不卡在线观看| 成人理论电影网| 欧美精品123区| 亚洲视频电影在线| 国产又粗又猛又爽又黄91精品| 播五月开心婷婷综合| 911精品国产一区二区在线| 中文字幕av不卡| 精品一区二区免费在线观看| 国产精品1区二区.| 欧美视频一二三区| 《视频一区视频二区| 国产一区二区伦理片| 3d动漫精品啪啪一区二区竹菊| 国产精品麻豆99久久久久久| 另类小说色综合网站| 欧美情侣在线播放| 尤物在线观看一区| 91在线看国产| 亚洲视频电影在线| 成人午夜视频在线观看| 精品99999| 亚洲成a人片在线观看中文| 不卡一区二区中文字幕| 精品国精品国产| 久久精品av麻豆的观看方式| 欧美日韩情趣电影| 亚洲成人福利片| 欧美三级日本三级少妇99| 亚洲日本在线观看| 99r国产精品| 亚洲视频一区在线观看| 成人av免费在线播放| 中文子幕无线码一区tr| 国产成a人亚洲| 国产三级精品视频| 大白屁股一区二区视频| 国产女同互慰高潮91漫画| 国产成人av影院| 欧美国产欧美综合| 国产不卡视频在线播放| 日韩网站在线看片你懂的| 亚洲综合激情网| 欧美日韩精品一区二区| 日韩影院在线观看| 日韩美女视频在线| 国产乱码精品1区2区3区| 337p日本欧洲亚洲大胆精品 | 亚洲欧美另类图片小说| 国产成人精品免费视频网站| 中文字幕+乱码+中文字幕一区| 成人精品视频网站| 亚洲国产一区在线观看| 欧美日韩国产电影| 久久爱www久久做| 欧美精品一区二区三区久久久| 奇米影视在线99精品| 久久色.com| 色综合久久中文字幕| 日韩国产在线一| 久久久久久久久一| 一本一道久久a久久精品| 一区二区三区免费观看| 91精品欧美综合在线观看最新 | 国产精品一级片在线观看| 欧美国产日韩a欧美在线观看 | ...av二区三区久久精品| 色欧美乱欧美15图片| 伊人婷婷欧美激情| 日韩精品在线看片z| 福利一区在线观看| 亚洲成人tv网| 国产丝袜在线精品| 日本二三区不卡| 狠狠色丁香婷婷综合| 亚洲另类色综合网站| 精品国产乱码久久久久久蜜臀| 91美女在线视频| 韩国三级电影一区二区| 亚洲一卡二卡三卡四卡| 久久亚洲精品小早川怜子| 在线影院国内精品| 国产精品系列在线观看| 午夜电影网一区| 国产精品久久久久久久久动漫 | 在线综合视频播放| 97久久超碰国产精品| 精久久久久久久久久久| 1024国产精品| 欧美三级视频在线观看| 成人黄色免费短视频| 蜜臀a∨国产成人精品| 亚洲欧美电影院| 中文在线一区二区| 日韩你懂的在线观看| 欧美在线观看一二区| 99久精品国产| 国产99精品国产| 韩国一区二区在线观看| 免费高清视频精品| 亚欧色一区w666天堂| 一区二区三区在线免费| 国产精品久久久久久久浪潮网站| 亚洲精品在线三区| 欧美乱妇23p| 在线观看日韩一区| 93久久精品日日躁夜夜躁欧美| 国产精品一区二区不卡| 精品一区二区三区免费| 久久电影国产免费久久电影| 水蜜桃久久夜色精品一区的特点| 亚洲日本va午夜在线影院| 中文字幕一区二区三中文字幕| 国产婷婷一区二区| 欧美成人精品3d动漫h| 91精品久久久久久久久99蜜臂| 欧美日韩午夜在线视频| 7777精品伊人久久久大香线蕉超级流畅 | 亚洲高清久久久| 亚洲最新在线观看| 亚洲综合色成人| 亚洲午夜一区二区三区| 国产欧美一区二区三区在线老狼| 欧美群妇大交群中文字幕| 欧美精品日韩精品| 日韩一级大片在线| 久久久久久久久伊人| 久久久久久免费网| 日韩一区有码在线| 亚洲va欧美va人人爽| 日韩成人免费电影| 国产精品夜夜爽| 9久草视频在线视频精品| 99视频精品免费视频| 一本到三区不卡视频| 国产91精品在线观看| 91一区一区三区| 欧美日韩一二区| 欧美α欧美αv大片| 国产亚洲美州欧州综合国| 国产精品免费人成网站| 一区二区三区在线观看动漫| 婷婷成人激情在线网| 国内成+人亚洲+欧美+综合在线| 国产成人综合精品三级| 色狠狠一区二区三区香蕉| 欧美另类一区二区三区| 久久精品一区二区三区不卡牛牛 | 亚洲高清视频在线| 激情深爱一区二区| av在线这里只有精品| 在线不卡中文字幕播放| 欧美不卡一区二区三区四区| 综合欧美一区二区三区| 日韩中文字幕亚洲一区二区va在线 | 亚洲国产精品一区二区www在线 | 美女在线观看视频一区二区| 九色综合国产一区二区三区| 欧日韩精品视频| 国产女同互慰高潮91漫画| 久久国产综合精品| 欧美日韩精品高清| 亚洲精品视频自拍| 成人污污视频在线观看| 久久婷婷色综合| 污片在线观看一区二区| 一本色道**综合亚洲精品蜜桃冫| 国产亚洲成av人在线观看导航 | 亚洲va国产va欧美va观看| 9i在线看片成人免费| 国产精品久久毛片av大全日韩| 国产资源在线一区| 久久久久久久一区| 国内久久婷婷综合| 2017欧美狠狠色| 国产一区二区在线观看免费| 日韩小视频在线观看专区| 日本亚洲三级在线| 欧美一区二区女人| 国产综合色产在线精品| 日韩欧美国产三级电影视频| 石原莉奈一区二区三区在线观看| 欧美日韩国产在线播放网站| 五月天视频一区|