Redis4.0 より前はシングル スレッドで実行されていましたが、Redis4.0 以降はマルチスレッドのサポートが開始されました。 Redis 4.0 より前にシングル スレッドが使用されていた理由: 1. シングル スレッド モードは開発とデバッグに便利です; 2. Redis は内部で epoll ベースの多重化を使用します; 3. Redis の主なパフォーマンスのボトルネックはメモリまたはネットワーク帯域幅です。
(学習ビデオ共有: redis ビデオ チュートリアル)
Redis4 では、Redis のバージョンが異なると異なります。 0, Redis はシングル スレッドで実行されましたが、シングル スレッドだからといって効率が低いわけではありません。Nginx や Nodejs もシングル スレッド プログラムですが、効率は低くありません。
その理由は、Redis がメモリに基づいているためです。そのボトルネックは、CPU ではなく、マシンのメモリとネットワーク帯域幅にあります。CPU がボトルネックに達する前に、マシンのメモリがいっぱいになるか、帯域幅が限界に達する可能性があります。ボトルネック。したがって、CPU が主な理由ではないので、シングルスレッドを使用するのは当然ですが、マルチスレッドを使用するとさらに面倒になります。
しかし、Redis 4.0 では、バックグラウンド削除やその他の機能などのマルチスレッドのサポートが開始されました。
簡単に言うと、Redis は 4.0 より前にシングルスレッド モードを使用していました。その理由は次の 3 つです。
Redis をシングルスレッド モードで使用すると、その開発とメンテナンスがより簡単になります。シングルスレッド モードは開発とデバッグを容易にするため、シンプルです。
シングルスレッド モデルが使用されている場合でも、主に Redis が内部で epoll ベースの多重化を使用しているため、複数のクライアント リクエストを同時に処理できます。
Redis の場合、主なパフォーマンスのボトルネックは CPU ではなく、メモリまたはネットワーク帯域幅です。
しかし、Redis は 4.0 以降のバージョンで遅延削除 (非同期削除とも呼ばれる) を導入しました。これは、非同期メソッドを使用して Redis 内のデータを削除できることを意味します。例:
unlink key: del キーと同様に、指定したキーを削除します。キーが存在しない場合、キーはスキップされます。ただし、del はブロッキングを引き起こし、unlink コマンドは別のスレッドでメモリを再利用します。つまり、非ブロッキングです [http://www.redis.cn/commands/unlink.html];
flushdb async: 現在のデータベース内のすべてのデータを削除します [http://www.redis.cn/commands/flushdb.html];
flushall async: 削除すべてのライブラリのすべてのデータ データ [http://www.redis.cn/commands/flushall.html]。
この処理の利点は、Redis のメイン スレッドが停止することがなく、これらの操作が実行のためにバックグラウンド スレッドに渡されることです。
[通常、del 命令を使用するとデータをすばやく削除できますが、削除されたキーが非常に大きなオブジェクトである場合、たとえば、数千の要素を含むハッシュ セットを削除する場合、del 命令により Redis エラーが発生します。メインスレッドがフリーズするため、遅延削除を使用すると、Redis のフリーズ問題を効果的に回避できます。 ]
テスト ポイント分析:
Redis スレッド モデル (シングルスレッドまたはマルチスレッド) に関する質問は、Redis が尋ねなければならない質問のほぼ 1 つですが、うまく答えられる人は多くはありません。ほとんどの人は、Redis がシングルスレッドであることと、シングルスレッドの多くの利点を述べるだけしかできませんが、特に Redis4.0 と Redis6.0 のマルチスレッドの特性については正確に答えることができます。 Redis6.0では人が少ないです。シングルスレッドとマルチスレッドの関連知識に関しては、次のような面接の質問もあります。
1. Redis のメインスレッドはシングルスレッドであるのに、なぜこれほど高速なのでしょうか?
2. Redis に IO 多重化を導入しますか?
3. Redis6.0 でマルチスレッドを導入しますか?
1. Redis はなぜそれほど速いのでしょうか?
理由は次のとおりです:
a. メモリベースの操作: Redis のすべてのデータはメモリに保存されるため、すべての操作はメモリ レベルで行われるため、パフォーマンスは比較的低くなります。高い。
b. シンプルなデータ構造: Redis のデータ構造は比較的シンプルで、Redis 用に特別に設計されており、これらのシンプルなデータ構造の検索と操作の時間計算量は O(1) です。
c. 多重化およびノンブロッキング IO: Redis は、IO 多重化機能を使用して複数のソケット接続を持つクライアントをリッスンするため、1 つのスレッドを使用して複数の状況を処理できるようになり、スレッドが削減されます。また、IO ブロック操作も回避されるため、Redis のパフォーマンスが大幅に向上します。
d. コンテキストの切り替えを回避する: シングルスレッド モデルであるため、不必要なコンテキストの切り替えとマルチスレッドの競合が回避され、マルチスレッドの切り替えによって生じる時間とパフォーマンスのオーバーヘッドが節約されます。デッドロックの問題を引き起こさないようにします。
公式ベンチマーク テストの結果は、シングルスレッド Redis が 10W/S のスループットを達成できることを示しています。
2.IO多重化とは何ですか?
ソケットの読み取りメソッドと書き込みメソッドはデフォルトでブロックされています。たとえば、読み取り操作の読み取りメソッドが呼び出されたとき、バッファーにデータがない場合、スレッドは次の処理が完了するまでここでスタックします。バッファにデータがある場合、または接続が閉じられると、読み取りメソッドが戻り、スレッドは他のビジネスの処理を続行できます。
しかし、これは明らかにプログラムの実行効率を低下させ、Redis はノンブロッキング IO を使用します。つまり、IO の読み取りおよび書き込みプロセスがブロックされなくなり、読み取りおよび書き込みメソッドが完了して即座に返されます。つまり、IO 操作を実行するために、読み取り可能な限り読み取り、書き込み可能な限り書き込みを行うという戦略が使用されます。これは明らかにパフォーマンスの追求により一致します。
しかし、この種のノンブロッキング IO には問題もあります。つまり、読み取り操作を実行するときに、データの一部だけが読み取られる可能性があります。同じことがデータの書き込みにも当てはまります。バッファがいっぱいで、データがまだ書き込まれていない場合、有効なデータがいつ書き込まれるかが問題になります。
IO の多重化により、上記の問題は解決されます。IO 多重化を使用する最も簡単な方法は、select 関数を使用することです。この関数は、オペレーティング システムがユーザー プログラムに提供する API インターフェイスです。使用するために使用されます。複数のファイル記述子の読み取り可能性と書き込み可能性を監視して、ファイル記述子の読み取りおよび書き込みイベントを監視できます。対応する時間を監視すると、スレッドに対応するビジネスを処理するよう通知できるため、Redis の読み取りおよび書き込み機能が正常に実行されることが保証されます。
[ただし、select 関数は基本的に現在のオペレーティング システムには適用できず、代わりに epoll 関数 (Linux) が呼び出されます。macOS では、select 関数が非常に重要であるため、Kqueue (Unix から継承) が使用されます。ファイル記述子が多いと、パフォーマンスが非常に低下します。 】
3. Redis6.0 でのマルチスレッド?
Redis のシングルスレッドの利点は非常に大きく、Redis の内部実装の責任が軽減されるだけでなく、すべての操作をロックなしで実行できるため、デッドロックやデッドロックが発生することもありません。スレッドの切り替え、パフォーマンスと時間の消費、しかしその欠点も明らかです。シングルスレッドのメカニズムでは、Redis の QPS (Query Per Second、1 秒あたりのクエリ数) を効果的に改善することが困難です (十分な速度ではありますが、ユーザーは依然としてより高速な処理を行う必要があります)。追跡)。
Redis はバージョン 4.0 でマルチスレッドを導入しましたが、このバージョンのマルチスレッドは大量のデータの非同期削除にのみ使用でき、削除以外の操作にはあまり意味がありません。
Redis マルチスレッドを使用すると、Redis の同期読み取りおよび書き込み IO のプレッシャーを共有し、マルチコア CPU リソースを最大限に活用し、Redis の QPS を効果的に向上させることができます。 Redis は IO 多重化を使用し、ノンブロッキング IO に基づいて動作しますが、IO 自体の読み取りと書き込みはブロッキングです。たとえば、ソケットにデータがある場合、Redis はまずカーネル空間からユーザー空間にデータをコピーし、その後関連する操作を実行しますが、このコピー プロセスがブロックされており、データ量が多くなると、これらの操作は単一のスレッドに基づいて完了します。
したがって、IO 読み取りおよび書き込みパフォーマンスを向上させるために、新しいマルチスレッド機能が Redis6.0 に追加されました。その主な実装アイデアは、メインスレッドの IO 読み取りおよび書き込みタスクをグループに分割することです。独立したスレッド: 実行により、複数のソケットの読み取りと書き込みを並列化できますが、Redis コマンドは依然としてメインスレッドによってシリアルに実行されます。
ただし、注意: Redis6.0 はデフォルトでマルチスレッドを無効にしますが、構成ファイル redis.conf の io-threads-do-reads を true に設定することで有効にできます。しかし、それだけでは不十分です。さらに、マルチスレッド機能を正しく有効にするためにスレッド数を設定する必要もあります。また、Redis 構成を変更する必要もあります。たとえば、io-threads 4 を設定すると、4 つのスレッドが開かれることになります。
[スレッド数の設定については、4 コア CPU の場合は 2 または 3 に、8 コア CPU の場合は 2 または 3 に設定することが公式推奨されています。つまり、スレッド数はマシンの CPU コア数よりも小さい必要があり、スレッド数は多ければ多いほど良いです。 】
Redis のパフォーマンスに関して、Redis の作成者は 2019 RedisConf カンファレンスで、Redis 6.0 で導入されたマルチスレッド IO 機能によりパフォーマンスが少なくとも 2 倍になったと述べました。また、中国人は Alibaba Cloud 上の 4 スレッド Redis バージョンとシングルスレッド Redis バージョンを使用して比較テストを実施しましたが、テスト結果は Redis 作者の発言と一致しており、基本的にパフォーマンスが 2 倍になる可能性があることがわかりました。
概要:
この記事では、Redis が 4.0 より前のシングル スレッドでも高速である理由を紹介します。これは、メモリ操作、シンプルなデータ構造、IO 多重化とノンブロッキング IO、不要なスレッドの回避に基づいています。コンテキストの切り替え。そして Redis 4.0 では、マルチスレッドのサポートが開始されました。これは主に、リンク解除キー、flushdb async、flushall async などのビッグデータの非同期削除に反映されています。 Redis 6.0 のマルチスレッドにより、IO 読み取りおよび書き込みの同時実行機能が向上し、Redis のパフォーマンスが向上します。
プログラミング関連の知識について詳しくは、プログラミング教育をご覧ください。 !
以上がRedis はシングルスレッドですか?それともマルチスレッドですか?なぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。