《Redis官方文件》Redis事件庫
Redis實現了自己的事件庫,程式碼在ae.c
中。想要理解Redis事件庫的工作原理,最好的方法就是去理解Redis如何使用它。
事件迴圈初始化
redis.c
中的initServer
函式初始化了redisServer
結構體變數的眾多成員,其中一個就是Redis事件迴圈(event loop)el
:
1 aeEventLoop *el
initServer
呼叫aeCreateEventLoop
(定義在ae.c
)初始化server.el
的成員。aeEventLoop
的定義如下:
01 typedef struct aeEventLoop
02 {
03 int maxfd;
04 long long timeEventNextId;
05 aeFileEvent events[AE_SETSIZE]; /* 已經註冊的事件 */
06 aeFiredEvent fired[AE_SETSIZE]; /* 已經就緒的事件 */
07 aeTimeEvent *timeEventHead;
08 int stop;
09 void *apidata; /* 這是polling API使用的專有資料 */
10 aeBeforeSleepProc *beforesleep;
11 } aeEventLoop;
aeCreateEventLoop
aeCreateEventLoop
首先為aeEventLoop
結構體分配記憶體,然後呼叫ae_epoll.c:aeApiCreate
。aeApiCreate
分配aeApiState
的空間,它有兩個成員:epfd
儲存epoll_create
呼叫返回的epoll
檔案描述符,events
是Linux epoll
庫中定義的epoll_event
結構型別。後面會再介紹events
的使用。
接下來是ae.c:aeCreateTimeEvent
,但是在那之前,initServer
會先呼叫anet.c:anetTcpServer
建立一個監聽描述符(listening descriptor),預設監聽6379埠。返回的監聽描述符儲存在server.fd
。
aeCreateTimeEvent
aeCreateTimeEvent
接收如下引數:
-
eventLoop
:即redis.c
中的server.el
。 - milliseconds:從當前時間開始距離定時器過期的毫秒數。
-
proc
:函式指標,儲存了定時器過期後呼叫的函式地址。 -
clientData
: 通常是NULL
。 -
finalizerProc
:指向定時事件被移除前要呼叫的函式。
initServer
呼叫aeCreateTimeEvent
為server.el
中的timeEventHead
成員新增一個定時事件,timeEventHead
是指向定時事件連結串列的指標。如下是 redis.c:initServer
函式中呼叫aeCreateTimeEvent
的程式碼。
1 aeCreateTimeEvent(server.el /*eventLoop*/, 1 /*milliseconds*/, serverCron /*proc*/, NULL /*clientData*/, NULL /*finalizerProc*/);
redis.c:serverCron
執行很多後臺操作來保持Redis正常運轉。
aeCreateFileEvent
aeCreateFileEvent
函式實質就是執行epoll_ctl
系統呼叫,以將anetTcpServer
建立的監聽描述符增加到EPOLLIN
事件佇列,並將它和aeCreateEventLoop
建立的epoll
描述符相關聯。
下面解釋了 redis.c:initServer
中呼叫aeCreateFileEvent
具體做的工作。initServer
傳遞了如下引數給aeCreateFileEvent
:
-
server.el
:aeCreateEventLoop
建立的事件迴圈,epoll
描述符是從server.el
裡獲取的。 -
server.fd
:監聽描述符,作為從eventLoop->events
中獲取相關檔案事件結構體的索引,結構體中儲存了回撥函式等資訊。 -
AE_READABLE
:表示必須監視server.fd
的EPOLLIN
事件。 -
acceptHandler
:當被監聽的事件就緒時執行的函式,函式指標儲存在eventLoop->events[server.fd]->rfileProc
。
以上完成了Redis事件迴圈的初始化。
事件迴圈的處理
redis.c:main
通過呼叫ae.c:aeMain
來處理前一階段初始化好的事件迴圈。ae.c:aeMain
在一個while迴圈中呼叫ae.c:aeProcessEvents
來處理就緒的定時事件和檔案事件。
aeProcessEvents
ae.c:aeProcessEvents
在事件迴圈上呼叫ae.c:aeSearchNearestTimer
尋找最先要過期的定時事件。我們的示例中,事件迴圈裡只有ae.c:aeCreateTimeEvent
建立的一個定時事件(譯者注:即前面呼叫ae.c:aeCreateTimeEvent
使用的回撥redis.c:serverCron
)。
請記住,aeCreateTimeEvent
建立的定時事件很可能已經過期了,因為過期時間只有1毫秒。定時器過期後,timeval
結構體的tvp
變數會把成員變數秒和毫秒都重置為0。tvp
結構體變數和事件迴圈變數作為引數傳給了ae_epoll.c:aeApiPoll
。aeApiPoll
函式在epoll
描述符上呼叫了epoll_wait
,然後用下面內容填充 eventLoop->fired
陣列。
-
fd
:準備好做讀/寫操作的描述符,操作型別取決於mask值。 -
mask
:標識讀/寫事件可以在對應描述符上執行。(譯者注:有讀事件mask |= AE_READABLE
,有寫事件mask |= AE_WRITABLE
)
aeApiPoll
返回已就緒事件的個數。來看個實際的例子,假設有客戶端發起了連線請求,那麼aeApiPoll
將會注意到,使用監聽描述符填充eventLoop->fired
陣列的描述符成員,把mask設為AE_READABLE
。
現在,aeProcessEvents
呼叫redis.c:acceptHandler
回撥函式。acceptHandler
在監聽描述符上執行accept,返回一個客戶端連線描述符。redis.c:createClient
通過下面這樣呼叫ae.c:aeCreateFileEvent
,向連線描述符新增一個檔案事件。
1 if (aeCreateFileEvent(server.el, c->fd, AE_READABLE,
2 readQueryFromClient, c) == AE_ERR) {
3 freeClient(c);
4 return NULL;
5 }
c
是redisClient
結構體變數,c->fd
是連線描述符。
然後,ae.c:aeProcessEvent
呼叫ae.c:processTimeEvents
。
processTimeEvents
ae.processTimeEvents
從 eventLoop->timeEventHead
開始,依次遍歷連結串列上的定時事件。
對每個過期的定時事件,processTimeEvents
呼叫相應的回撥函式。這個示例只會呼叫唯一註冊的定時事件回撥函式redis.c:serverCron
,回撥函式返回的時間表示多少毫秒後它將被再次呼叫。返回的時間被ae.c:aeAddMilliSeconds
記錄下來,ae.c:aeMain
中的while迴圈會在下次迭代中繼續處理定時事件。
就這些了。
相關文章
- 《Redis官方文件》sentinelRedis
- 《Redis官方文件》持久化Redis持久化
- Redis-py官方文件翻譯Redis
- Redis分散式鎖(Redlock官方文件的理解)Redis分散式
- Redis文件Redis
- 《Redis官方教程》-FAQRedis
- UNITY官方文件:事件函式Unity事件函式
- redis事件機制Redis事件
- redis-官方cluster分割槽Redis
- Redis的事件機制Redis事件
- Redis筆記(10):事件Redis筆記事件
- Redis 5.02官方叢集搭建Redis
- 《Redis官方教程》-基準測試Redis
- PHP-redis中文文件PHPRedis
- Redis 事件機制詳解Redis事件
- Redis 中的事件迴圈Redis事件
- Redis勒索事件爆發,如何避免從刪庫到跑路?Redis事件
- Redis面試題-Redis 16個資料庫Redis面試題資料庫
- 【Redis系列】Spring boot實現監聽Redis key失效事件RedisSpring Boot事件
- 資料庫-Redis資料庫Redis
- java 監聽 redis 過期事件JavaRedis事件
- redis的事件處理機制Redis事件
- Redis 中的事件驅動模型Redis事件模型
- Cocos Creator 玩家輸入事件(摘自官方文件)事件
- Redis官方視覺化工具RedisInsightRedis視覺化
- RedisInsight :Redis 官方視覺化工具Redis視覺化
- Redis——Redis用作資料庫(持久化/RDB/AOF)Redis資料庫持久化
- Redis資料庫4:Go與Redis的互動Redis資料庫Go
- Redis(1)- Redis資料庫的安裝和配置Redis資料庫
- Redis Stack:基於Redis的搜尋、文件、圖形和時間序列功能Redis
- 【Redis】Redis 初探Redis
- REDIS主從頻繁切換事件排查Redis事件
- Redis的KEYS命令引起當機事件Redis事件
- Redis 原始碼學習之事件驅動Redis原始碼事件
- redis個人原始碼分析筆記3---redis的事件驅動原始碼分析Redis原始碼筆記事件
- Redis 資料庫安裝Redis資料庫
- redis資料庫遷移Redis資料庫
- Redis 4.0.10 中文文件(完整的命令列表)Redis命令列