Redisは現在よく知られているインメモリデータベースであり、さまざまなシナリオで非常に豊富なアプリケーションがあります。少し前に、Redisは6.0バージョンをリリースし、新しいバージョンでマルチスレッドモデルを採用しました。
当社が使用しているインメモリデータベースは自社開発であるため、Redisにあまり注意を払っていないのは当然ですが、Redisは広く使用されているため、インタビューを容易にするためにこれを理解する必要があります。
候補者はRedisを使用できませんが、Ali'sTairで何が起こっているのかを他の人に尋ねる必要があります。
それで、Redis 6.0のリリース後、マルチスレッドが使用される理由を理解したいと思います。現在使用されているマルチスレッドと以前のバージョンの違いは何ですか?マルチスレッドがそれほど遅く使用されているのはなぜですか?
Redisはすでに多重化テクノロジーを採用していませんか?高性能ではないですか?なぜマルチスレッドモデルを使用するのですか?
この記事では、これらの問題とその背後にある考え方を分析します。
そもそもRedisがシングルスレッドになるように設計されたのはなぜですか?
成熟した分散キャッシュフレームワークとして、Redisは、ネットワークリクエストモジュール、インデックスモジュール、ストレージモジュール、高可用性クラスターサポートモジュール、データ操作モジュールなど、多くのモジュールで構成されています。
多くの人がRedisはシングルスレッドであると言い、Redisのすべてのモジュールの操作はシングルスレッドであると考えていますが、実際、これは間違っています。
Redisシングルスレッドと呼ばれるものは、「ネットワークIOとキーと値のペアの読み取りと書き込みが1つのスレッドで完了する」ことを意味します。つまり、Redisのネットワーク要求モジュールとデータ操作モジュールのみがシングルスレッドです。 。永続ストレージモジュールやクラスターサポートモジュールなど、その他はマルチスレッドです。
そのため、Redisにはマルチスレッドモデルがないわけではありません。Redis4.0の初期には、一部のコマンドはマルチスレッド化されていました。
では、そもそもネットワーク操作モジュールとデータストレージモジュールがマルチスレッドを使用しなかったのはなぜですか?
この質問への答えは比較的簡単です!理由:「必要ありません!」
なぜ不要なのですか?最初にそれについて話しましょう。どのような状況でマルチスレッドを使用する必要がありますか?
マルチスレッドアプリケーションのシナリオ
コンピュータプログラムの実行中に実行する必要がある2つの主要な操作があります:読み取りおよび書き込み操作と計算操作。
その中で、読み取りおよび書き込み操作は、主にネットワークI / OおよびディスクI / Oを含むI / O操作に関連しています。計算操作は主にCPUに関係します。
マルチスレッドの目的は、I / Oの使用率とCPUの使用率を同時に改善することです。
では、Redisはマルチスレッドを使用してI / Oの使用率とCPUの使用率を改善する必要がありますか?
まず、Redisの操作は基本的にメモリに基づいており、CPUリソースはRedisのパフォーマンスのボトルネックではないため、RedisはCPU使用率を改善する必要がないことを確信できます。
したがって、マルチスレッド技術によってRedisのCPU使用率を改善する必要はまったくありません。
では、マルチスレッドテクノロジーを使用してRedis I / Oの使用率を向上させるのはどうでしょうか。必要ですか?
Redisは確かに、集中的なI / O操作を行うフレームワークです。データ操作中は、多くのネットワークI / OとディスクI / Oが発生します。Redisのパフォーマンスを向上させたい場合は、RedisのI / O使用率を上げる必要があります。これは間違いありません。
ただし、マルチスレッドテクノロジを使用する方法は、I / O使用率の向上だけではありません。
マルチスレッドのデメリット
メモリモデル、ロック、CASなど、多くの記事でJavaのマルチスレッドテクノロジを紹介しています。これらは、マルチスレッドの場合にスレッドの安全性を確保するためにJavaで提供されるテクノロジです。
スレッドセーフ:プログラミングの用語であり、並行環境で関数または関数ライブラリが呼び出されたときに複数のスレッド間で共有変数を正しく処理して、プログラム関数を正しく完了できるようにする機能を指します。
Javaと同様に、マルチスレッドをサポートするすべてのプログラミング言語またはフレームワークは、問題、つまり、マルチスレッドプログラミングモデルによって引き起こされる共有リソースの同時実行制御の問題をどのように解決するかという問題に直面する必要があります。
マルチスレッドを使用すると、CPUとI / Oの使用率を向上させることができますが、マルチスレッドによって引き起こされる同時実行の問題も、これらの言語とフレームワークをより複雑にします。さらに、マルチスレッドモデルでは、複数のスレッドを切り替えると、特定のパフォーマンスオーバーヘッドも発生します。
したがって、I / O使用率を向上させるという観点から、Redisはマルチスレッドテクノロジを使用せず、多重化I / Oテクノロジを選択します。
概要
Redisは、主に次の4つの理由に基づいて、ネットワーク要求モジュールとデータ操作モジュールでマルチスレッドモデルを使用しません。
- 1. Redis操作はメモリに基づいており、ほとんどの操作のパフォーマンスのボトルネックはCPUにありません
- 2.シングルスレッドモデルを使用すると、保守性が高くなり、開発、デバッグ、およびメンテナンスのコストが低くなります。
- 3.シングルスレッドモデルは、スレッド間の切り替えによって引き起こされるパフォーマンスのオーバーヘッドを回避します
- 4.シングルスレッドで多重化I / Oテクノロジーを使用すると、RedisのI / O使用率も向上します。
まだ覚えておく必要があります。Redisは完全にシングルスレッドではありませんが、キーネットワークIOとキーと値のペアは1つのスレッドによって読み書きされます。
Redis多重化
マルチプレックスという用語は多くの人が知っていると思います。私は以前の記事の多くでこの用語について十分に言及しました。
その中で、Linux IOモデルを導入したときに言及し、HTTP / 2の原理を導入したときにも言及しました。
では、Redisの多重化テクノロジーと以前に導入したテクノロジーの違いは何ですか?
最初にLinux多重化テクノロジーについて説明します。つまり、複数のプロセスのIOを同じパイプに登録でき、このパイプはカーネルと統一された方法で相互作用します。パイプライン内の特定のリクエストに必要なデータの準備ができると、プロセスは対応するデータをユーザースペースにコピーします。

上の写真と上の文をもう一度読んでください。後で使用できます。
つまり、複数のIOストリームが1つのスレッドで処理されます。
IO多重化には、Linuxで、select、poll、epollの3つのタイプがあります。抽象的な観点からは、それらの機能は似ていますが、具体的な詳細は異なります。
実際、RedisのIO多重化プログラムのすべての機能は、オペレーティングシステムのIO多重化機能ライブラリをパッケージ化することによって実現されます。各IO多重化機能ライブラリには、Redisソースコードに対応する個別のファイルがあります。

Redisでは、ソケットが接続応答、書き込み、読み取り、クローズなどの操作を実行する準備ができるたびに、ファイルイベントが生成されます。サーバーは通常複数のソケットに接続するため、複数のファイルイベントが同時に表示される場合があります。

リクエストが到着すると、処理のためにRedisスレッドに渡されます。これにより、1つのRedisスレッドが複数のIOストリームを処理する効果が得られます。
そのため、Redisは多重化IOテクノロジーを使用してI / O使用率を向上させることを選択しました。
Redisがこのような高いパフォーマンスを発揮できる理由は、多重化テクノロジとシングルスレッドの使用だけでなく、次の理由にも関係しています。
1.完全にメモリに基づいているため、ほとんどの要求は純粋なメモリ操作であり、非常に高速です。
2.データ構造がシンプルで、ハッシュテーブルやジャンプテーブルなどのデータ操作もシンプルで高性能です。
3.シングルスレッドは、不要なコンテキストの切り替えや競合条件を回避するために使用され、CPUを消費するマルチプロセスまたはマルチスレッドによって引き起こされる切り替えはありません。
4.複数のI / O多重化モデルを使用する
Redis6.0がマルチスレッドを導入する理由
2020年5月、Redisはバージョン6.0を正式にリリースしました。このバージョンには多くの重要な新機能があり、その中でマルチスレッド機能が広く注目されています。
ただし、Redis 6.0のマルチスレッドはネットワーク要求の処理にのみマルチスレッドを使用し、データの読み取りおよび書き込みコマンドは依然としてシングルスレッドであることを全員に思い出させる必要があります。
ただし、誰かがこの質問をしているのかどうかはわかりません。
Redisは、高性能でシングルスレッドであると主張していませんか?
多重化技術によってIO使用率が大幅に向上したということではありませんが、なぜマルチスレッドが必要なのですか?
主な理由は、Redisの要件が高いためです。
計算によると、Redisはすべてのデータをメモリに格納し、メモリの応答時間は約100ナノ秒です。小さなデータパケットの場合、Redisサーバーは80,000〜100,000 QPSを処理できます。企業の80%の場合、シングルスレッドのRedisで十分です。使用する。
ただし、ビジネスシナリオがますます複雑になると、一部の企業では毎ターン数億のトランザクション量が発生するため、より高いQPSが必要になります。
QPSを改善するために、多くの企業がRedisクラスターをデプロイし、Redisマシンの数を可能な限り増やしています。しかし、このアプローチのリソース消費は膨大です。
分析後、Redisのパフォーマンスを制限する主なボトルネックは、ネットワークIOの処理に現れますが、以前は多重化テクノロジーが使用されていました。ただし、前述したように、多重化IOモデルは本質的に同期ブロッキングIOモデルです。
多重化IOでの選択機能の処理プロセスは次のとおりです。

上の図から、多重化IOモデルでは、ネットワーク要求を処理するときに、select(他の関数は同じ)を呼び出すプロセスがブロックされていることがわかります。つまり、このプロセスは、量があればスレッドをブロックします。同時実行性が非常に高いため、ここがボトルネックになる可能性があります。
現在、多くのサーバーに複数のCPUコアがありますが、Redisの場合、単一のスレッドを使用するため、データ操作中のネットワークIOの同期に大量のCPUタイムスライスが費やされます。マルチコアの利点を十分に活用していません。 。
複数のスレッドを使用してネットワーク処理要求を同時に実行できる場合、パフォーマンスを大幅に向上させることができます。マルチスレッドは、ネットワークI / O待機による影響を軽減するだけでなく、CPUのマルチコアの利点を最大限に活用することもできます。
そのため、Redis 6.0は複数のIOスレッドを使用してネットワーク要求を処理します。ネットワーク要求の分析は他のスレッドで完了でき、解析された要求は実際のメモリの読み取りと書き込みのためにメインスレッドに渡されます。ネットワーク要求処理の並列処理を改善し、それによって全体的なパフォーマンスを改善します。
ただし、RedisのマルチIOスレッドは、ネットワーク要求の処理にのみ使用されます。読み取りおよび書き込みコマンドの場合、Redisは引き続き単一のスレッドを使用して処理します。
では、マルチスレッドの導入後、並行性によって引き起こされるスレッドセーフの問題をどのように解決するのでしょうか。
これが、「Redis 6.0のマルチスレッドはネットワーク要求の処理にのみ使用され、データの読み取りと書き込みはシングルスレッドのままである」と何度も言及した理由です。
Redis 6.0は、ネットワークリクエストを受信して解析するとき、およびリクエストされたデータがネットワークを介して返されるときにのみマルチスレッドを使用します。データの読み取りおよび書き込み操作は引き続き単一のスレッドによって実行されるため、同時実行の問題は発生しません。
参考資料:
https://www.cnblogs.com/Zzbj/p/13531622.html https://xie.infoq.cn/article/b3816e9fe3ac77684b4f29348 https://jishuin.proginn.com/p/763bfbd2a1c2 "Geek Time:Redis Core"技術と実際の戦闘