Redis のシングルスレッドとマルチスレッド

Redis のコア処理ロジックは常にシングルスレッドであり、一部のブランチ モジュールはマルチスレッドです(UNLINK、FLUSHALL ASYNC、FLUSHDB ASYNC、その他のノンブロッキング削除操作など、一部の非同期プロセスは 4.0 以降マルチスレッドを使用します。ネットワークI/O ソリューション パッケージは 6.0 からマルチスレッドを使用します ;)

なぜシングルスレッドなのか

複数のコアを活用するマルチスレッドはどの程度優れていますか?

公式説明

これは、Redis の位置付けがメモリ kv ストレージであり、短期的かつ高速なホットスポット データ処理に使用されることを意味します。一般に、実行は非常に高速になります。実行自体はボトルネックではありません。ボトルネックは通常、ネットワーク I/O。論理マルチスレッドの処理はそれほど難しくはなく、大きなメリットがあります。
同時に、Redis 自体もシンプルさと効率の概念を堅持しています。コードのシンプルさと保守性は Redis の長年の追求でした。マルチスレッドの導入によってもたらされる複雑さは想像をはるかに超えており、マルチスレッドの導入によってもたらされる複雑さは想像をはるかに超えています。スレッド化自体にも追加コストが発生します。

1. マルチスレッドの導入により大きな複雑さがもたらされる


1. まず第一に、マルチスレッドの導入後、Redis の元の逐次実行機能は存在しなくなり、トランザクションのアトミック性と分離をサポートするために、Redis はいくつかの非常に複雑な実装を導入する必要があります
。 Redis の構造は非常に効率的です。多くの機能の最適化はシングル スレッド モードで行われています。マルチ スレッドを導入すると、
基礎となるすべてのデータ構造をスレッド セーフに変換する必要があり、これは非常に複雑な作業になります。3.
さらに、 、マルチスレッド モードにより、プログラムのデバッグも容易になります。複雑さとトラブルにより、追加の開発コストと運用コストが発生し、間違いも犯しやすくなります (MYSQL の同時実行性を思い出してください...)

2. マルチスレッド化により追加コストが発生する

1. コンテキスト切り替えコスト。マルチスレッド スケジューリングには、スレッド コンテキストの切り替えが必要です。この操作では、まず現在のスレッドのローカル データ、プログラム ポインターなどを保存し、次に別のスレッドのデータをロードします。このカーネル操作のコストは、無視されました。
2. 同期メカニズムのオーバーヘッド。一部のパブリック リソースはシングル スレッド モードで直接アクセスできます。マルチスレッドはロックやその他の方法で同期する必要があります。これも無視できない CPU オーバーヘッドです。3.
スレッドサイズ、Redis のようなインメモリ データベースの場合、メモリは非常に貴重であり、マルチスレッド自体によってもたらされるメモリ使用量のコストについても、慎重な意思決定が必要です。
 

シングルスレッドはなぜそれほど速いのでしょうか?

第一に、Redis のほとんどの操作はメモリ内で完了し、メモリ操作自体が非常に高速です。第
二に、Redis は究極を追求し、多くの効率的なデータ構造を選択し、ziplist、ハッシュ、スキップなどの多くの最適化を行っています。テーブル。さまざまなシナリオに対処するために、オブジェクトの基礎となる実装が複数存在する場合があります。
3 番目に、Redis は多重化メカニズムを使用して、ネットワーク I0 操作で多数のクライアント要求を同時に処理し、高いスループットを実現できるようにします。
1点目と2点目は非常にわかりやすいのですが、3点目はどうでしょうか。

I/0 多重化とは? 簡単に言うと、I/0 操作がトリガーされると通知が生成され、通知を受信した後、通知に対応するイベントが処理されます。 Reactor モデルと呼ばれるパッケージングの層。
本質は、さまざまなイベントをリッスンし、イベントが発生したときに、そのイベントをさまざまなプロセッサに分散することです。

このようにして、特定の操作でブロックされることはなく、パフォーマンスが最大限に発揮されます。I/O 多重化により、Redis シングル スレッドの同時実行性が向上すると言えます。これは同時実行であり、並列処理ではないことに注意してください。このモードでは、Redis シングルコアの性能が最大限に発揮されると言えます。
 

しかし

現在のビジネスボリュームは本当に大きすぎます

前述したように、Redis がシングルスレッドを選択する主な理由は、Redis はすべてメモリ操作であり、CPU 処理が非常に高速であるためであり、ボトルネックは CPU よりも I/O に現れる可能性が高いため、シングルスレッド モデルが選択されました。 。

時代の発展に伴い、多くの企業のリクエスト量はかつては想像もできなかったレベルに達しており、確かにI/O操作がボトルネックとなっていますが、これまでのRedisの処理プロセスでは、リクエストの読み込みと返信パケットの送信がすべてI/Oでした。そこで、Redis はマルチスレッドを導入しました。ここでのマルチスレッドとは、処理ロジック全体がマルチスレッドであることを意味するものではありません。これを行う場合、すべてのデータ構造をスレッドセーフに再構築する必要があります。これは膨大なコストであり、 「不可能かもしれません。どれくらい改善されていますか? 損失によって減少する可能性さえあります。結局のところ、ボトルネックはほとんどの場合対処されていません。実際、ボトルネックは一般的にネットワーク I/O にあります。」
上記の状況のた​​め、Redis はネットワーク I/O を処理するためにマルチスレッドを導入することを選択しましたが、それでも Redis コマンドを実行するためにシングルスレッド フレームワークを使用しました。これにより、Redis コアのシングルスレッド処理アーキテクチャが維持されるだけでなく、完全に以前の実装と互換性がありますが、マルチスレッドも導入されており、ネットワーク I/O パフォーマンスの向上の問題を解決します。
 

マルチスレッドについて詳しく知る必要はありません

まず、マルチスレッドは 6.0 以降に導入されました。データ量の増加に対処するために、デフォルトではオフになっています。.conf で変更できます。マルチスレッドはネットワーク I/O の処理を​​担当します。具体的には

命令を読み取って解析し、パケットを返します。

シングルスレッド モードでは、1 つのスレッドが読み取り、解析、実行を完了し、戻りパケットをクライアント バッファに入れます
が、マルチスレッド モードでは、別のクライアントが client_pending_read タスク キューに入れられ、後続の呼び出しは、 Round -Robin ラウンドロビン負荷分散戦略は、これらのクライアントを他の IO スレッドと、読み取りと解析用のメイン スレッドに割り当てます。パケットを返すとき、Round-Robin ラウンドロビン負荷分散戦略も使用され、タスクを継続的かつ均等に分散します。パケットの戻りを待っているキュー内のパケットは、
IO スレッドとメイン スレッド自体のそれぞれのローカル FIFO タスク キューに割り当てられ、メイン スレッドはポーリングして、すべての IO スレッドがパケットの戻りタスクを完了するのを待ちます。

おすすめ

転載: blog.csdn.net/chara9885/article/details/132237193