ホームページ  >  記事  >  データベース  >  この記事では、Redis のスレッド IO モデルをすぐに理解できるようにします。

この記事では、Redis のスレッド IO モデルをすぐに理解できるようにします。

青灯夜游
青灯夜游転載
2021-12-21 10:19:322425ブラウズ

Redis はシングルスレッドですが、なぜこれほど高速なのでしょうか?理由の 1 つは、redis がノンブロッキング IO と多重化を使用して多数のクライアント接続を処理するためです。次の記事では、Redis のスレッド IO モデルについて説明します。お役に立てば幸いです。

この記事では、Redis のスレッド IO モデルをすぐに理解できるようにします。

Redis はシングルスレッド アプリケーションであり、NodeJs と Nginx はどちらもシングルスレッドであり、いずれも高性能サーバーのモデルです。 [関連する推奨事項: Redis ビデオ チュートリアル ]

Redis がシングルスレッドで高速である理由:

まず、すべてのデータがメモリ内にあるため、すべての操作がメモリレベルの操作なので、redis を使用する場合は、時間計算量が O(n) の命令に注意してください。シングルスレッドであるため、データ量が多すぎると、他の命令がブロックされて待機します。

#2 番目の理由は、redis がノンブロッキング IO と多重化を使用して多数のクライアント接続を処理するためです。

ノンブロッキング IO

ソケットの読み取りおよび書き込みメソッドを使用する場合、デフォルトはブロックです。

つまり、読み取りメソッドを呼び出してパラメーターを渡します。 n、読み取りの最大数を示します n バイトを取った後に戻ります。バイトがない場合、スレッドはデータが到着するか接続が閉じられるまで読み取りメソッドで待機し続けます。読み取りメソッドはこの時点で戻り、スレッドは次のロジックを実行できます。

書き込みメソッドは通常、ブロックしません。カーネルによってソケットに割り当てられた書き込みバッファーがいっぱいでない限り、バッファーに空き領域ができるまで、書き込みメソッドはブロックされます。

次の図は、ソケットの読み取りと書き込みの詳細なプロセスを示しています。

この記事では、Redis のスレッド IO モデルをすぐに理解できるようにします。

ノンブロッキング IO では、ソケットを使用するときに Non_Blocking オプションが提供されます。このオプションをオンにすると、読み取りメソッドと書き込みメソッドはブロックされませんが、ブロックされるのと同じだけ読み取ることができます。できる限り書き込めます。

どれだけ読み取れるかは、カーネルによってソケットに割り当てられた読み取りバッファ内のデータ バイト数によって決まり、どのくらい書き込めるかはデータによって決まります。カーネルによってソケットの書き込みバッファに割り当てられます。バイト数、

読み取りメソッドと書き込みメソッドは、戻り値を通じてプログラムに読み書きされたバイト数を通知します。

ノンブロッキング IO とは、読み取りおよび書き込み時にスレッドをブロックする必要がなくなったことを意味します。読み取りと書き込みは即座に完了し、スレッドは他の作業を続行できます。

多重化 (イベント ポーリング)

ノンブロッキング IO は非常に高速ですが、問題も発生します。スレッドはデータを読み取り、その一部を読み取った後に戻ります。読み取りが完了していません。 . 残りのデータはいつ読み続けられますか? 、データを書き込んでいますが、バッファーがいっぱいで完全に書き込まれていません。残りのデータはいつ書き続けられますか?

読み取りを継続できる場合、または書き込みを継続できる場合は、アプリケーションに読み取りまたは書き込みを継続できることを通知する通知を送信する必要があります。この問題を処理するには、イベント ポーリング API が使用されます。

select

オペレーティング システムは、ユーザー プログラムの選択機能を提供します。入力は、読み取りおよび書き込み記述子リスト read_fds および write_fds です。出力は、対応する読み取り可能および書き込み可能なイベントです。

はタイムアウト パラメーターも提供します。スレッドは最大でタイムアウトまで待つことができます。この期間中、イベントが発生すると、メソッドはすぐに戻ります。スレッドは処理を続行します。タイムアウト時間を超えた場合、メソッドも戻ります。

イベントが取得されると、スレッドは対応するイベントを 1 つずつ処理できます。処理後、メソッドの呼び出しを継続します。 select API ポーリングなので、スレッドは実際には無限ループであり、選択を続けます。ノンストップで処理を行ったり来たりするこの無限ループはイベント ループと呼ばれ、ループはサイクルです。

この記事では、Redis のスレッド IO モデルをすぐに理解できるようにします。

イベント ループ疑似コード:

while True
    read_events, write_events = select(read_fds, write_fds, timeout)
    for event in read_events:
        handle_read(event.fd)
    for event in write_events:
        handle_write(event.fd)
    handle_others() # 做其他的逻辑处理,处理定时任务等等

select 関数を通じて、複数のチャネル記述子の読み取りおよび書き込みイベントを処理できるため、select のようなシステムは、この呼び出しは多重化 API と呼ばれます。

最新のオペレーティング システムの多重化 API では、select システム コールは使用されなくなり、代わりに epoll (linux) と kqueue (FreeBSD、macosx) が使用されます。記述子の数が増えると、select の処理は非常に貧弱になります。epoll と select の使い方には若干の違いがありますが、上記の疑似コードを使用して理解できます。記述子でイベントが発生すると、記述子はループされます。イベントが処理されます。

serversocket オブジェクトの読み取り操作は、クライアントからの新しい接続を受け入れるために accept を呼び出すことを参照します。接続が確立されると、select によって呼び出される読み取りイベントを通じて通知されます。

Java の NIO テクノロジはイベント ポーリングであり、他の言語にもこのテクノロジがあります。

コマンド キュー

Redis はコマンド キューを各クライアント ソケットに関連付け、クライアントから送信されたコマンドはキューを通じて先入れ先出しの順序で処理されます。

Response Queue

同様に、Redis から返される結果も、各クライアントに関連付けられたキューを通じて返されます。キューが空の場合は、当面書き込みイベントを取得する必要はありません,

このとき、クライアント記述子は write_fds から削除され、キューにデータがある場合は記述子が追加されます。これにより、select システム コールのときに書き込むデータがないことが判明するのを回避できます。書き込みイベントを返すため、空きスペースが発生し、ポーリング、無駄なポーリング、マシン CPU の消費が発生します。

タイミング タスク

サーバーは IO イベントに応答する必要があるだけでなく、アプリケーション自身のタイミング タスクなど、他のことも処理する必要があります。スレッドが選択呼び出しでブロックした場合、待機中になります。 select が返されると、一部のスケジュールされたタスクは期限切れになっていますが、実行されていません。

Redis のスケジュールされたタスクは、最小ヒープと呼ばれるデータ構造に記録されます。このヒープでは、最も速いタスクが実行されます。各サイクル サイクル中、redis はその時点に達したヒープ内のタスクを処理します。ヒープが記録されます。select が再度呼び出されるとき、この時間は になります。タイムアウトの値は、この期間中に他のタスクを実行する必要がないことを意味します。Redis は最大でこの時間の間は安全にブロックでき、その後、対応する処理を実行します。時間切れです。

NodeJ と Nginx のイベント処理原理は Redis と似ています。

プログラミング関連の知識について詳しくは、

プログラミング ビデオ

をご覧ください。 !

以上がこの記事では、Redis のスレッド IO モデルをすぐに理解できるようにします。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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