Redis Queue StreamとRedisマルチスレッドの詳細解説(3)

Redis のスレッドと IO モデル

Reactor パターンとは何ですか?

「リアクター」という装置の名前の「反応」の由来:

「リアクション」とは、「反転」や「制御の逆転」を意味します。特定のイベント ハンドラーは、リアクターを呼び出すのではなく、リアクターにイベント ハンドラーを登録し、特定のイベントに興味があることを示します。時間が来ると、特定のイベント ハンドラーがリアクターに登録します。イベント ハンドラーを通じて指定されたイベントの発生に反応します。この制御の逆転は「ハリウッドの法則」としても知られています (電話しないでください、電話させてください)

たとえば、通行人 A がメンズエステに行き、フロントの受付係が通行人 A を迎えます。通行人 A は今 10,000 人の技術者にしか興味がありませんが、通行人 A は先に行ったため、受付係に 10,000 人の技術者が仕事中であることを伝えます。または無料です。、気づいてください。通行人Aさんは受付の女性から通知を受けると対応し、1万人の技術者を占拠した。

すると、通行人Aさんは、10000号室が快適な設備と薄暗い照明で良い部屋だったことを思い出し、フロントの受付のお姉さんに「10000号室に興味があるので、空いたら連絡してください」と伝えました。女性は自分の人生について雑談し、10000号室は空室になりました、通行人Aは再び受付女性から通知を受け、通行人Aは再び応答しました。

通行人Aは特定イベント処理プログラム フロント受付はいわゆるリアクター 「10000人の技術者が出勤中」と「10000号室が空いています」がイベント 通行人Aはこの2つのイベントのみに興味がある その他、10001 などの技術者 1 号または 10002 号室が空いているというイベントもありますが、通行人 A は興味がありません。

フロントの受付嬢は、通行人Aだけでなく、通行人B、Cの接客も同時に行っており、人それぞれ興味のあるイベントは異なりますので、フロントの受付嬢がそれぞれに案内します。人それぞれが興味のあるイベントに合わせて、人それぞれに対応します。

シングルスレッド Reactor モードのプロセス

サーバー側の Reactor はスレッド オブジェクトであり、イベント ループを開始し、Acceptor イベント ハンドラーを使用して ACCEPT イベントに注意を払うため、Reactor はクライアントによって開始された接続要求イベント (ACCEPT イベント) をリッスンします。サーバーに。

クライアントはサーバーへの接続リクエストを開始し、Reactor は ACCEPT イベントの発生を監視し、処理のために対応する Acceptor プロセッサに ACCEPT イベントをディスパッチします。接続が確立されたら、Reactor が接続の READ イベントをリッスンできるように、READ イベントに注意してください。

Reactor は、READ イベントの発生を検出すると、関連するイベントを対応するプロセッサに送信して処理します。たとえば、読み取りプロセッサはデータを読み取りますが、この時点で、read() 操作は、読み取り可能なデータの到着をブロックしたり待機したりすることなく、データを直接読み取ることができます。

現在のシングルスレッド Reactor モードでは、I/O 操作が Reactor スレッドで実行されるだけでなく、I/O 以外のビジネス操作もこのスレッドで処理されるため、I/O リクエストの応答が大幅に遅れる可能性があります。したがって、I/O リクエストに対する Reactor スレッドの応答を高速化するには、I/O 以外のビジネス ロジック操作を Reactor スレッドからオフロードする必要があります。

 シングルスレッド Reactor、ワーカー スレッド プール

シングルスレッド Reactor モードとは異なり、ワーカー スレッド プールが追加され、非 I/O 操作は実行のために Reactor スレッドからワーカー スレッド プールに移動されます。これにより、Reactor スレッドの I/O 応答が向上し、時間のかかるビジネス ロジックによって後続の I/O リクエストの処理が遅延することがなくなります。

ただし、一部の小容量アプリケーション シナリオではシングル スレッド モデルを使用できますが、高負荷、大規模な同時実行性、または大量のデータ量を伴うアプリケーション シナリオには適していません。主な理由は次のとおりです。

① 1 つの NIO スレッドが数百のリンクを同時に処理するため、パフォーマンス的にサポートできず、NIO スレッドの CPU 負荷が 100% に達しても、大量のメッセージの読み取りと送信を満足できません。

② NIO スレッドが過負荷になると処理速度が低下し、多数のクライアント接続がタイムアウトし、タイムアウト後の再送信が頻繁に発生するため、NIO スレッドの負荷が増大し、最終的には大量のメッセージのバックログと処理タイムアウトがシステムのパフォーマンスのボトルネックになります。

 マルチリアクタースレッドモード

Reactor スレッド プール内の各 Reactor スレッドには、配布用の独自のセレクター、スレッド、およびイベント ループ ロジックがあります。

mainReactor は 1 つだけ存在できますが、通常は複数の subReactor が存在します。mainReactor スレッドは主にクライアントからの接続要求を受信し、受信した SocketChannel を subReactor に渡し、subReactor がクライアントとの通信を完了します。

マルチ Reactor スレッド モードでは、「クライアントの接続要求の受け付け」と「クライアントとの通信」を 2 つの Reactor スレッドに分割して完了します。mainReactor は、クライアント接続リクエストの受信操作を完了します。クライアントとの通信は行いませんが、確立された接続を subReactor スレッドに転送して、クライアントとの通信を完了します。このようにして、クライアントとの通信が原因で大量のデータが発生することはありません。 read() その結果、後続のクライアント接続要求をすぐに処理できなくなります。また、マルチ Reactor スレッド モードでは、多数のクライアント リクエストが同時に発生した場合に、subReactor スレッド プールを実装することで大規模な接続を複数の subReactor スレッドに分散することもできます。これにより、マルチコア動作におけるアプリケーションの負荷とスループットが大幅に向上します。システム数量。

 Redis のスレッドと IO の概要

Redis は、Reactor モデルに基づいて独自のネットワーク イベント ハンドラー - ファイル イベント ハンドラー (以下、FEH) を開発しており、プロセッサはシングルスレッドであるため、redis はシングルスレッド モデルとして設計されています。

I/O 多重化を使用して複数のソケットを同時に監視し、ソケットによって現在実行されているイベントに応じて、ソケットに対応するイベント ハンドラーを選択します。

監視対象のソケットが受け入れ、読み取り、書き込み、クローズなどの操作を実行できる状態になると、その操作に対応するファイル イベントが生成されます。このとき、FEH はソケットに関連付けられたイベント ハンドラーを呼び出して、ファイルを処理します。対応するイベント。

したがって、FEH はシングル スレッドで実行されますが、I/O 多重化によって複数のソケットが監視されます。これにより、高性能のネットワーク通信モデルが実現されるだけでなく、Redis サーバーの同じシングル スレッドで実行される他のモジュールと対話し、シングルスレッドモデル向けの Redis 内部のクリーンな設計。

ファイル イベント ハンドラーのいくつかのコンポーネントを見てみましょう。

 ソケット

ファイル イベントはソケット操作の抽象化であり、ソケットが接続の受け入れ、読み取り、書き込み、クローズなどの操作を実行する準備ができると、ファイル イベントが生成されます。通常、サーバーは複数のソケットに接続し、複数のソケットが異なる操作を同時に生成することがあり、各操作は異なるファイル イベントに対応します。

I/Oマルチプレクサ

I/O マルチプレクサは、複数のソケットをリッスンする役割を果たします。

ファイル イベントは同時に発生する可能性がありますが、I/O マルチプレクサはイベントを生成するすべてのソケットをキューに入れ、整然と同期した方法で、一度に 1 ソケットずつ、キューを通じてソケットをファイル イベント ディスパッチャに送信します。

前のソケットによって生成されたイベントが対応するイベント ハンドラーによって実行されると、I/O 多重化プログラムは次のように次のソケットをファイル イベント ディスパッチャーに送信します。

I/O多重化プログラムの導入

Redis の I/O 多重化プログラムのすべての機能は、select、epoll、evport、kqueue などの共通の I/O 多重化関数ライブラリをラップすることで実現されます。

各 I/O 多重化ライブラリは、Redis ソース コード内の個別のファイルに対応します。

Redis は各 I/O マルチプレクサー ライブラリに同じ API を実装しているため、基礎となる I/O マルチプレクサーの実装は交換可能です。Redis は、I/O 多重化プログラムのソース コードの「ae.c」ファイル内で対応するルールを定義します。これにより、プログラムは、システム内で最も高いパフォーマンスを持つ I/O 多重化関数ライブラリを Redis 低機能ライブラリとして自動的に選択します。 I/O マルチプレクサのレベル実装: パフォーマンスの降順。

ノート:

evport = Solaris 10

epoll = Linux

kqueue = OS X、FreeBSD

select = 通常、すべてのプラットフォームにフォールバックとしてインストールされます

Evport、Epoll、および KQueue の記述子選択アルゴリズムの複雑さは O(1) であり、それらはすべて内部カーネル空間メモリ構造を使用しており、多数 (数十万) のファイル記述子を提供することもできます。

とりわけ、select は最大 1024 個の記述子しか提供できず、記述子のフル スキャンを実行する (つまり、毎回すべての記述子を反復して使用可能な記述子を選択する) ため、複雑さは O(n) です。

ファイルイベントディスパッチャ

ファイルイベントディスパッチャは、I/O多重化プログラムからソケットを受け取り、ソケットによって生成されたイベントタイプに応じて、対応するイベントハンドラを呼び出します。

ファイルイベントハンドラ

サーバーは、さまざまなタスクを実行するソケットにさまざまなイベント ハンドラーを関連付けます。これらのハンドラーは、イベントの発生時にサーバーが実行するアクションを定義する関数です。

Redis は、さまざまなファイル イベント要件に対応する複数のプロセッサを記述しています。クライアントが Redis に接続し、サーバーに接続されている各クライアントに応答する場合、ソケットを接続応答プロセッサにマップして、Redis にデータを書き込み、クライアントからデータを受信する必要があります。コマンドリクエストは、Redisからデータを読み込み、コマンドの実行結果をクライアントに返すためにコマンドリクエストプロセッサにマッピングする必要があります コマンドリプライプロセッサにマッピングする必要があります マスターサーバーとスレーブサーバーが実行する際レプリケーション操作では、マスター サーバーとスレーブ サーバーの両方が、コピー機能専用に作成されたコピー プロセッサにマップする必要があります。

ファイルイベントの種類

I/O多重化プログラムは、複数のソケットのae.h/AE_READABLEイベントとae.h/AE_WRITABLEイベントを監視できますが、これら2種類のイベントとソケットの動作の対応は以下のとおりです。

ソケットが読み取り可能な場合 (たとえば、クライアントが Redis で書き込み/クローズ操作を実行する場合)、または新しい応答可能なソケットが表示される場合 (つまり、クライアントが Redis で接続操作を実行する場合)、ソケットは AE_READABLE イベントを生成します。

ソケットが書き込み可能な場合 (たとえば、クライアントが Redis で読み取り操作を実行する場合)、ソケットは AE_WRITABLE イベントを生成します。

I/O 多重化プログラムは、AE_REABLE イベントと AE_WRITABLE イベントの両方を同時に監視できます。ソケットがこれら 2 つのイベントを同時に生成した場合、ファイル イベント ディスパッチャーは AE_REABLE イベントを優先します。つまり、ソケットが読み取り可能と書き込み可能の場合、Redis サーバーは最初に読み取りを行い、次にソケットに書き込みます。

要約する

最後に、クライアントと Redis サーバー間の通信プロセス全体を整理しましょう。

Redis は初期化を開始すると、接続応答ハンドラーを AE_READABLE イベントに関連付けます。

クライアントが接続を開始すると、AE_READABLE イベントが生成され、接続応答プロセッサはクライアントとの接続を確立し、クライアントに対応するソケットを作成し、同時にこのソケットの AE_READABLE イベントを関連付けます。コマンド要求プロセッサーを使用して、クライアントのコマンド要求をマスターサーバーに送信できるようにします。

クライアントが Redis にリクエストを送信すると (読み取りリクエストまたは書き込みリクエストに関係なく)、クライアント ソケットは AE_READABLE イベントを生成してコマンド リクエスト プロセッサをトリガーします。プロセッサはクライアントのコマンドの内容を読み取り、実行のために関連するプログラムに渡します。

Redis サーバーがクライアントに応答する準備ができると、ソケットの AE_WRITABLE イベントをコマンド応答プロセッサに関連付けます。クライアントが応答データを読み取る準備ができると、ソケット上で AE_WRITABLE イベントが生成され、対応するコマンドがプロセッサに応答し、準備された応答データをクライアントが読み取るためにソケットに書き込む処理が行われます。

コマンド応答プロセッサがソケットへの書き込みを完了すると、ソケットの AE_WRITABLE イベントとコマンド応答プロセッサの間のマッピングが削除されます。

おすすめ

転載: blog.csdn.net/yaya_jn/article/details/130224729