ホームページ  >  記事  >  データベース  >  Redis の epoll および file イベントについて説明する記事

Redis の epoll および file イベントについて説明する記事

青灯夜游
青灯夜游転載
2021-11-03 10:55:141868ブラウズ

この記事では、Redis のファイル イベントについて紹介します。一定の参考価値があります。困っている友人は参照してください。お役に立てれば幸いです。

Redis の epoll および file イベントについて説明する記事

イベント駆動型

Redis サーバーはイベント駆動型のプログラムであり、 ファイル イベント と 2 つに分かれています。 時間イベント

  • ファイル イベント: ソケットの読み取りおよび書き込み可能なイベント
  • 時間指定タスク

[関連する推奨事項:Redisビデオ チュートリアル]

これらはすべて aeEventLoop 構造にカプセル化されています

typedef struct aeEventLoop {
	int stop; // 标识事件是否结束
	aeFileEvent *events; // 文件事件数组,存储已注册的文件事件
	aeFireEvent *fired; // 存储被触发的文件事件
	aeTimeEvent *timteEventHead; // 多个时间事件形成的链表
	void *apidata; // I/O模型的封装
	aeBeforeSleepProc *beforesleep; // 进程阻塞前执行
	aeBeforeSleepProc *aftersleep; // 进程被唤醒后执行
} aeEventLoop;

イベント ドライバーは実際には while/for もループします。イベントの発生をループで待機しています

while (! eventLoop->stop) {
	if (eventLoop->beforesleep != NULL)
		eventLoop->beforesleep(eventLoop)
	aeProcessEvents(eventLoop, AE_ALL_EVENTS|AE_CALL_AFTER_SLEEP);
}

aeProcessEventsイベント処理のメイン関数

epoll

Redis クライアント経由TCP ソケット サーバーと対話する場合、ファイル イベントはソケットの読み取り可能および書き込み可能なイベントを指します。一般に、ノンブロッキング モードが使用され、関連する I/O 多重化には、select/epoll/kqueue などが含まれます。オペレーティング システムが異なれば、実装も異なります。

epoll を例に挙げると、これは、多数の同時ネットワーク接続を処理するために Linux カーネルによって提案されたソリューションです。 epoll3 つの API を提供します

  • epoll_create は、後続の epoll 関連 API 呼び出し用に epoll 固有のファイル記述子を作成します

int epoll_create(int size)
// size 告知内核程序期望注册的网络连接数目,Linux 2.6.8后改为内核动态分配
// 返回参数是 epoll 专用的文件描述符
  • epoll_ctl 関数は、epoll で監視する必要があるイベントを登録、変更、または削除します。

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
// epfd 函数 epoll_create 返回的 epoll 文件描述符
// op 操作类型 EPOLL_CTL_ADD:注册事件; EPOLL_CTL_MOD:修改网络连接事件; EPOLL_CTL_DEL:删除事件
// fd 网络连接的 socket 文件描述符
// event 需要监控的事件
  • epoll_wait 関数は、イベントの監視が発生するまでプロセスをブロックします。複数のネットワーク接続で

  • #
    int epoll_wait(int epfd, struct epoll_event *event, int maxevents, int timeout)
    // epfd 函数epoll_create返回的epoll文件描述符
    // epoll_event 作为输出参数使用,用于回传已触发的事件数组
    // maxevents 每次能处理的最大事件数目
    // timeout epoll_wait 函数阻塞超时时间,如果超过 timeout 时间还没有事件发生,函数就不再阻塞直接返回;当 timeout 等于0是函数立即返回,timeout 等于-1时函数一直阻塞到有事件发生

ファイル イベント

Reids は epoll API を直接使用しませんが、4 種類の I/O をサポートします。同時に、O 多重化モデルはこれらのモデルの API をカプセル化します。次に、コンパイル段階で、オペレーティング システムがサポートする I/O 多重化モデルがチェックされ、戦略に従ってどのモデルを再利用するかが決定されます。

epoll を例に挙げると、Redis は次のようにカプセル化されます。

// 对应 epoll_create
static int aeApiCreate(aeEventLoop *eventLoop)

// 对应 epoll_ctl 添加事件
static int aeApiAddEvent(aeEventLoop *eventLoop, int fd, int mask)
// 对应 epoll_ctl 删除事件
static int aeApiDelEvent(aeEventLoop *eventLoop, int fd, int delmask)

// 对应 epoll_wait
static int aeApiPool(aeEventLoop *eventLoop, struct timeval *tvp)

前述の

eventLoop 構造を思い出してください。そのメンバー apidata は 4 種類の I/O 複数を指します。道路再利用モデル オブジェクト。イベントは監視する必要があるイベント配列を格納し、要素にアクセスするための配列インデックスとしてソケット ファイル記述子を使用します。fired はトリガーされたイベント配列を格納します。

ファイル イベントの構造は次のように定義されます。

typedef struct aeFileEvent {
	int mask; // 文件事件类型 AE_READABLE 可读事件;AE_WRITEABLE 可写事件
	aeFileProc *rfileProc; // 读事件处理函数指针
	aeFileProc *wfileProc; // 写事件处理函数指针
	void *clientData; // 指向对应的客户端对象
} aeFileEvent;

ファイル作成イベント aeCreateFileEvent の実装を見てください

int aeCreateFileEvent (aeEventLoop *eventLoop, int fd, int mask, aeFileProc *proc, void *clientData) {
	aeFileEvent *fe = &eventLoop->evnts[fd];
	if (aeApiAddEvent(eventLoop, fd, mask) == -1)
		return AE_ERR;
	fe->mask |= mask;
	if (mask & AE_READABLE) fe->rfileProc = proc;
	if (mask & AE_WRITABLE) fe->wfileProc = proc;
	fe->clientData = clientData;
	return AE_OK;
}

Redis サーバーは、さまざまなファイルを作成することでトランザクションを処理します。次のようなファイル イベント:

    起動時にソケットを作成してリッスンし、クライアントの接続を待機します
  • aeCreateFileEvent(server.el, server.ipfd[j], AE_READABLE, acceptTcpHandler, NULL);
    クライアントがソケット接続を確立した後、サーバーはクライアントのコマンド要求を待ちます。
  • aeCreateFileEvent(server.el, fd, AE_READABLLE, readQueryFromClient, c);
    サーバーがクライアントのコマンド要求を処理した後、コマンド応答はクライアント構造の buf バッファーに一時的にキャッシュされます。クライアントのファイル記述子の書き込み可能なイベントが発生し、コマンド応答が実際にクライアント
  • aeCreateFileEvent(server.el, c->fd, AE_READABLLE, sendReplyToClient, c);
Redis に送信されます。すべてのイベントの実行は、

aeProcessEvents 関数を通じて制御されます。このうち、ファイルイベントの実行によりブロッキング(epoll_wait)が発生し、ブロッキングイベントが長すぎると時間イベント(タイミング)の実行に支障をきたすため、ファイルイベント実装時に待ち時間を設け、これは、発生した最も古いイベントを計算することによって取得されます

int aeProcessEvents(aeEventLoop *eventLoop, int flags) {
	shortest = aeSearchNearestTimer(eventLoop);
	long long ms = (shortest->when_sec - now_sec) * 1000 + \
		shortest->when_ms - now_ms;

	// 阻塞事件发生
	numevents = aeApiPoll(eventLoop, ms);

	for (j=0; j < numevents; j++) {
		aeFileEvent *fe = &eventLoop->events[eventLoop->fired[j]].fd];
		// 处理文件事件,即根据类型执行rfileProc或wfileProc
	}

	// 处理时间事件
	processed += processTimeEvents(eventLoop);
}

概要

次に、Redis サーバーの対応するコマンドのプロセスを全体的に見てみましょう

Redis の epoll および file イベントについて説明する記事

aeMain 関数は、aeProcessEvents 関数を呼び出して、ファイル イベントと時間イベントをスケジュールおよび実行します。イベント関連の情報は aeEventLoop に記録されます。まず、aeSearchNearestTimer 関数を通じて最短時間イベントの実行時間間隔 n を取得し、次に aeApiPoll 関数を呼び出して監視対象ソケットを取得し、最後にソケットに対応するイベント処理関数 rfileProc および wfileProc を実行し、最後に時間イベントを実行します。関数 processTimeEvents 。

完全なクライアント/サーバー接続イベント:

  • #サーバーはパッケージの AE_READABLE イベントをリッスンします。クライアントが接続要求を送信し、AE_READABLE イベントを生成すると、 、サーバーはクライアントの接続リクエストに応答し、クライアントソケットの AE_READABLE イベントとコマンドリクエスト処理関数 (aeFileProc) を組み合わせ、クライアントはコマンドリクエストをサーバーに送信できます

  • サーバーはコマンド要求を送信し、クライアント ソケットは AE_READABLE イベントを生成し、コマンド プロセッサの実行をトリガーします。コマンドを実行すると、対応するコマンド応答が生成されます。サーバーは、クライアント ソケットの AE_WRITABLE イベントとコマンドを組み合わせます。応答処理関数 (aeFileProc) 関連するエンドがコマンド応答を読み取ろうとすると、クライアント ソケットは AE_WRITABLE イベントを生成し、コマンド応答プロセッサの実行をトリガーします。コマンド応答プロセッサがすべてのコマンド応答を書き込むとき、ソケットに入ると、サーバーは、クライアントソケットの AE_WRITABLE イベントとコマンド応答処理関数 (aeFileProc) の間の関連付けに接続します (aeFileProc)

プログラミング関連の知識について詳しくは、プログラミング ビデオをご覧ください。 !

以上がRedis の epoll および file イベントについて説明する記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。