Kafka の優れた高性能設計 パート 2

Kafka の優れた高性能設計 パート 2

[[429455]]

みなさんこんにちは。私はウー兄弟です。

これは、「Mastering MQ Series」の第 2 部「Kafka の高パフォーマンス設計」です。前回の記事では、高性能設計の 2 つの重要な側面、つまり「Tao」として理解できるコンピューティングと IO について説明しました。同時に、カフカの高性能なデザインを俯瞰することができ、それは「芸術」として理解することができます。

図1: Kafkaの高性能設計の概要

この記事では、メッセージを保存および消費するための 8 つの高性能設計手法を 1 つずつ分析していきます。さっそく始めましょう。

1. メッセージ保存のパフォーマンス最適化方法

メッセージの保存はブローカーのコア機能です。使用される最適化方法は次の 4 つです。

1. IO多重化

Kafka ブローカーの場合、高いパフォーマンスを実現するために最初に考慮すべきことは、ブローカーとプロデューサーおよびコンシューマー間のメッセージ転送の問題を処理するための効率的なネットワーク通信モデルを設計することです。

まず、Kafka 2.8.0 ソース コードの SocketServer クラスにある重要なコメントを引用します。

このコメントを通じて、Kafka が非常に典型的な Reactor ネットワーク通信モデルを使用していることが実際にわかります。完全なネットワーク通信層フレームワーク図は次のとおりです。

図2: Kafkaネットワーク通信層のフレームワーク図

単純なメモリは 1 + N + M です。

  • 1: 1 つの Acceptor スレッドを示します。これは、新しい接続をリッスンし、新しい接続を Processor スレッドに渡して処理する役割を担います。
  • N: N 個のプロセッサ スレッドを表します。各プロセッサには独自のセレクタがあり、ソケットからのデータの読み取りと書き込みを担当します。
  • M: M 個の KafkaRequestHandler ビジネス処理スレッドを表します。これらのスレッドは、KafkaApis を呼び出してビジネス処理を実行し、応答を生成して Processor スレッドに渡します。

IO を研究した人なら、Reactor モードが従来の IO 多重化テクノロジを使用していることは明らかです。スレッドを再利用して多数のソケット接続を処理できるため、高いパフォーマンスが保証されます。 Netty と Redis が数十万、あるいは数百万もの同時接続を実現できるのはなぜでしょうか?実際、どちらも Reactor ネットワーク通信モデルを使用しています。

2. ディスクシーケンシャル書き込み

IO 多重化によるネットワーク通信が完了したら、ブローカーが次に考慮する必要があるのは、メッセージをすばやく保存する方法です。記事「Kafka ストレージ選択の秘密」では、Kafka がメッセージを保存するために「ログ ファイル」を使用することが述べられています。では、このディスク ファイル書き込み方法はどのようにして高いパフォーマンスを実現するのでしょうか?これらはすべてディスクの順次書き込みによるものです。それをどう理解すればいいのでしょうか?メッセージ キューとしての Kafka は、本質的には先入先出のキューであり、メッセージが生成されると不変になります。この秩序性と不変性により、Kafka はログ ファイルを順番に「書き込む」、つまり、ファイルの末尾にメッセージを追加するだけが可能になります。逐次書きを前提として、比較実験を見てみましょう。下の図から、ディスクのシーケンシャル書き込みのパフォーマンスはディスクのランダム書き込みよりもはるかに高く、メモリのランダム書き込みよりもさらに高いことがわかります。

図3: ディスクとメモリのIO速度の比較

その理由は非常に単純です。通常の機械式ディスクの場合、ランダム書き込み、つまりファイルの特定の場所を見つけてデータを書き込むだけの場合、パフォーマンスが非常に低くなります。しかし、シーケンシャルに書き込むと、ディスクのシークとディスクの回転にかかる時間が大幅に節約されるため、パフォーマンスが 3 桁向上します。

3. ページキャッシュ

ディスクのシーケンシャル書き込みはすでに非常に高速ですが、メモリのシーケンシャル書き込みに比べるとまだ数桁遅いです。さらに最適化することは可能ですか?答えはイエスです。

ここで Kafka はページ キャッシュ テクノロジーを使用します。簡単に言えば、オペレーティングシステム自体のキャッシュ技術を使用します。ディスク ログ ファイルの読み取りと書き込みを行う際、操作は実際にはメモリ上で実行され、その後、オペレーティング システムがページ キャッシュ内のデータを実際にディスクにフラッシュするタイミングを決定します。次の例の図はこれを明確に示しています。

図4: Kafkaのページキャッシュの原理

では、ページ キャッシュはいつ最も効果を発揮するのでしょうか?これには、ページ キャッシュで使用される 2 つの古典的な原則について言及する必要があります。ページ キャッシュは、最近アクセスされたデータが次にアクセスされる可能性が高いという原則に基づく「時間的局所性」の原則を使用して、最近使用されるディスク データをキャッシュします。ページ キャッシュに事前に読み込まれたディスク データは、データが継続的にアクセスされることが多いという事実に基づいて、「空間的局所性」の原則を利用します。メッセージ キューとして、Kafka はメッセージを順番に書き込み、コンシューマーがそれをすぐに読み取ります。これは間違いなく、上記の 2 つの局所性原則に準拠しています。そのため、ページ キャッシュは Kafka が高スループットを実現するための重要な要素の 1 つであると言えます。

さらに、ページ キャッシュにはもう 1 つの大きな利点があります。 Java を使用したことがある人なら誰でも、ページ キャッシュを使用せずに JVM プロセス内のキャッシュを使用すると、オブジェクトのメモリ オーバーヘッドが非常に大きくなる (通常は実際のデータ サイズの数倍、あるいはそれ以上になる) ことを知っています。さらに、ガベージコレクションが必要となり、GC によって発生する Stop The World 問題もパフォーマンスの問題を引き起こします。ページ キャッシュには明らかな利点があり、Kafka のコード実装が大幅に簡素化されることがわかります。

4. パーティションとセグメントの構造

ディスクのシーケンシャル書き込みとページ キャッシュを組み合わせることで、ログ ファイルの高パフォーマンスな読み取りと書き込みの問題が効果的に解決されます。ただし、トピックが 1 つのログ ファイルのみに対応する場合、トピックは 1 つのブローカー マシンにのみ保存できることは明らかです。膨大な量のメッセージに直面すると、単一のマシンのストレージ容量と読み取り/書き込みパフォーマンスは確実に制限されるため、別の独創的なストレージ設計、つまりストレージ用のデータをパーティション分割することが必要になります。私の記事「Kafka アーキテクチャ設計の Ren 子午線と Du 子午線」では、パーティションの概念と役割について詳しく説明しました。パーティションは Kafka の同時処理の最小粒度であり、ストレージのスケーラビリティの問題を非常にうまく解決します。パーティションの数が増えると、Kafka のスループットがさらに向上します。実際、Kafka の最下部のストレージ レイヤーには、パーティションの下に別のレイヤー、つまり「セグメンテーション」があります。簡単に理解すると、パーティションは実際にはフォルダーに対応し、セグメントは実際のログ ファイルに対応します。

図5: Kafkaパーティションセグメントストレージ

各パーティションは複数のセグメントに分割されます。では、パーティションの後にセグメントが必要なのはなぜでしょうか?

セグメントが導入されていない場合、1 つのパーティションは 1 つのファイルのみに対応し、ファイルは大きくなり続けるため、必然的に単一のパーティション ファイルが大きくなりすぎて、検索や保守が不便になります。また、履歴メッセージを削除する場合は、ファイルの以前の内容を削除する必要があります。ファイルが 1 つしかないということは、明らかに Kafka の順次書き込みの考え方に準拠していません。セグメントが導入された後は、古いセグメント ファイルを削除するだけで、各セグメントの順次書き込みが保証されます。

2. メッセージ消費のパフォーマンス最適化手法

Kafka は、100 万 TPS の書き込みパフォーマンスを実現するだけでなく、高性能なメッセージ読み取りの問題も解決する必要があり、そうでなければ高スループットとは言えません。次に、Kafka がメッセージを消費するときに使用する 4 つの最適化方法を見てみましょう。

1. スパースインデックス

読み取りパフォーマンスを向上させるにはどうすればよいでしょうか?インデックス作成は誰でも簡単に考えられます。 Kafka が直面するクエリ シナリオは実際には非常に単純です。オフセットまたはタイムスタンプに従ってメッセージを検索できます。 B-Tree インデックス構造を使用する場合、データが書き込まれるたびにインデックスを維持する必要があり (ランダム IO 操作)、また、「ページ分割」などの時間のかかる操作も発生します。単純なクエリ要件のみを実装する必要がある Kafka にとって、これらのコストは非常に大きくなります。したがって、B-Tree インデックスは Kafka には適していません。逆に、ハッシュ インデックスが適しているようです。読み取り操作を高速化するには、オフセットからログ ファイル オフセットへのマッピング関係をメモリ内で維持するだけでよい場合は、オフセットに基づいてメッセージを検索するたびに、ハッシュ テーブルからオフセットを取得してファイルを読み取ることができます。 (同じ考え方は、タイムスタンプに基づいてメッセージを検索するために使用できます) ただし、ハッシュ インデックスはメモリ内に常駐し、大量のデータを処理できないのは明らかです。 Kafka は 1 秒あたり数百万のメッセージを書き込む可能性があり、メモリが確実にバーストします。しかし、メッセージのオフセットは順序付けされるように設計できることがわかりました (実際には単調に増加する long 型のフィールドです)。そのため、メッセージはログ ファイル自体に順序どおりに格納されます。メッセージごとにハッシュインデックスを構築する必要はありません。メッセージを複数のブロックに分割し、各ブロックの最初のメッセージのオフセットのみをインデックスすることができます。まずサイズ関係に基づいてブロックを見つけ、次にブロック内を順番に検索します。これがKafkaの「スパースインデックス」の設計思想です。

図6: Kafkaのスパースインデックス設計

「スパース インデックス」の使用は、ディスク領域、メモリ領域、検索パフォーマンスなど、多くの面で妥協点として考えられます。スパース インデックスでは、オフセットが指定されると、Kafka はバイナリ検索を使用して、オフセットを超えない物理的な変位を効率的に特定し、ターゲット メッセージを検索します。

2. mmap

スパース インデックスの使用により、効率的なクエリの問題は基本的に解決されましたが、このプロセスにはさらなる最適化の余地が残されています。つまり、上記のスパース インデックス ファイルを mmap (メモリ マップ ファイル) を介して読み書きし、メッセージのクエリ速度をさらに向上させる必要があります。

  • 注意: mmap とページ キャッシュは 2 つの異なる概念であり、多くのオンライン資料ではこれらが混同されています。さらに、Kafka はログファイルを読み取るときにも mmap を使用することを記載したドキュメントもあります。バージョン 2.8.0 のソースコード分析により、この情報も間違っていることがわかりました。実際には、インデックス ファイルの読み取りと書き込みにのみ mmap が使用されます。

mmap を理解するにはどうすればいいですか?前述したように、従来のファイル操作では、ページ キャッシュ メカニズムを使用して読み取りと書き込みのパフォーマンスが向上します。ただし、ページ キャッシュはカーネル空間にあり、ユーザー プロセスが直接アクセスすることはできないため、ファイルを読み取るときには、ページ キャッシュ内のデータを再度ユーザー空間にコピーするためのシステム コールが必要になります。 mmap を使用すると、ディスク ファイルがプロセスの仮想アドレスにマップされ、システム コールや追加のメモリ コピー オーバーヘッドが発生しなくなるため、ファイルの読み取り効率が向上します。

図 7: mmap 図、「Coder's Desert Island Survival」より引用

mmap に関しては、私の親友 Xiaofeng が非常に人気のある記事を書きました: mmap を使用すると、プログラマーはどのようなクールな操作をアンロックできるのでしょうか?参考にしていただけます。具体的には、Kafka ソース コード レベルでは、JDK nio パッケージの MappedByteBuffer のマップ関数に基づいて、ディスク ファイルをメモリにマップします。ログファイルで mmap が使用されないのはなぜでしょうか?これは実は非常に良い質問です。コミュニティはこの質問に対して公式の回答を出していないため、インターネット上の回答では作者の意図について推測することしかできません。私は個人的に、stackoverflow のこの回答に同意します:

mmap によってメモリにマップできるバイト数は、アドレス空間によって異なります。 32 ビット アーキテクチャでは、4 GB 以下のファイルしか処理できません。 Kafka ログは、一度に一部しかマップできないほど大きい場合が多く、読み取りが非常に複雑になります。ただし、インデックス ファイルはまばらで、比較的小さいです。これらをメモリにマップすると、検索プロセスが高速化されます。これがメモリ マップ ファイルによってもたらされる主な利点です。

3. ゼロコピー

スパース インデックスを使用してメッセージが照会された後、次のステップは、ディスク ファイルからメッセージを読み取り、ネットワーク カードを介してコンシューマーに送信することです。このステップをどのように最適化できますか? Kafka はパフォーマンスを向上させるためにゼロコピー テクノロジーを使用します。いわゆるゼロ コピーとは、アプリケーションを経由せずにディスク ファイルからネットワーク カード デバイスにデータが直接コピーされ、カーネルとユーザー モード間のコンテキスト切り替えが削減されることを意味します。

以下のプロセスは、ゼロコピー技術を使用しない場合に、ディスクからファイルを読み取り、ネットワーク カードを介して送信するプロセスです。 4 つのコピーと 4 つのコンテキスト スイッチが実行されていることがわかります。

図8: 非ゼロコピー技術のフローチャート(「艾小仙」より引用)

ゼロコピー技術(sendfile メソッドを通じて最下層に実装)を使用する場合、プロセスは次のようになります。ご覧のとおり、必要なのは 3 つのコピーと 2 つのコンテキスト スイッチだけであり、明らかにパフォーマンスが向上します。

図9: ゼロコピー技術のフローチャート(「艾小仙」より引用)

4. バッチプル

プロデューサーがメッセージをバッチで送信するのと同様に、メッセージ コンシューマーもメッセージをバッチでプルし、一度に 1 つのメッセージ セットをプルします。これにより、ネットワーク転送のオーバーヘッドが大幅に削減されます。さらに、Kafka の優れた高性能設計 (パート 1) で紹介したように、プロデューサーは実際にクライアント側でバッチ メッセージを圧縮します。これらのメッセージのバッチがブローカーに永続化されるとき、それらは圧縮されたままであり、最終的にコンシューマー側で解凍されます。

3. 最後に

以上が、Kafka の 12 の高性能設計手法の詳細な説明です。これら 2 つの記事では、まず IO とコンピューティングという 2 つの側面からマクロなアプローチを取り、次に MQ の 1 回の送信、1 回のストレージ、1 回の消費のコンテキストに沿って、ミクロの観点から Kafka の高パフォーマンスの全体像を分析します。 Kafka は、高性能設計の教科書的な例であると言えます。 Prodcuer から Broker、そして Consumer に至るまで、細部に至るまで慎重に最適化し、最終的に単一のマシンで毎秒数十万 TPS という究極のパフォーマンスを実現しました。

最後に、この記事の分析手法が他の高性能ミドルウェアの理解に役立つことを願っています。ウー兄弟です。また次回お会いしましょう!

<<:  マジック: メモリプーリングと分散 AI クラスターの最適化

>>:  おすすめする価値のある Kubernetes ダッシュボード ツール トップ 9

推薦する

従来のアーキテクチャは大きな変化を遂げ、分散型クラウドストレージが次世代のインフラストラクチャとなる

フォン・ノイマン・アーキテクチャの 5 つの要素のうち、コンピューティング、ストレージ、およびネット...

7 つの分散型グローバル ID 生成戦略のうち、どれがお好みですか?

[[415300]]マイクロサービスを使用することで、グローバル ID の問題など、もともと単純だっ...

ウェブマスターとして、隠しリンクの危険性についてどの程度ご存知ですか?

隠しリンクについては、皆さんもよくご存知だと思います。しかし、最近、私は多くの新しいウェブマスターの...

SEOの共有方法: ウェブサイトの修正に関するヒント

昨日、その友人は、私のウェブサイトにいくつかのコラムを追加して、私のWebサイトを見せてくれたことを...

クラウド コンピューティング戦略にセキュリティ対策を統合するための 5 つのヒント

多くの企業システム管理者は、組織のクラウドファースト戦略がビジネスセキュリティを危険にさらしていると...

ハイブリッドクラウドとマルチクラウドにおけるクラウドセキュリティの課題への対処方法

ハイブリッドおよびマルチクラウド環境には、複雑さと軽減戦略を伴うクラウド セキュリティの課題がいくつ...

ウェブホストの選び方

月収10万元の起業の夢を実現するミニプログラム起業支援プランはじめに: 優れた仮想ホストを選択する際...

オンライン共同購入業界の死亡率はほぼ半分であり、専門家はモデルの突破口を模索する必要があると述べている

2012 年は、さまざまな共同購入 Web サイトにとって間違いなく暗い年でした。倒産、合併・買収、...

毎日平均4つの共同購入サイトが閉鎖されている

最近、共同購入サイト「Juqi.com」は、内部の業務調整のためサービスを一時停止すると発表した。し...

心からお勧めします: Downtownhost 40% オフ プロモーション (シンガポール データ センターあり)

ダウンタウンホストは2001年5月に設立されました。最もお勧めの仮想ホストの1つだと思います。スピー...

Linode ブラックフライデーイベント、25 ドルをプレゼント!

Linode も毎年恒例のブラックフライデーに参加しています。Linode がユーザーに特典を提供す...

来年、電子商取引は大きな変化を迎えるだろう。一部の企業は株式を公開するかもしれない。

2013年、電子商取引は急速な発展の時代を迎えるでしょう。一方では、混乱後の電子商取引の情勢が徐々に...

ニュース記事の過剰問題についての簡単な議論

ソフト製品は理想的なマーケティングプロモーション手法ですが、人気が出たときから議論の的となってきまし...

アプリプロモーションのヒント: iOS チャネルを活用する 8 つの方法

質問1:iOSチャネルをどこで利用すればよいかわかりません。Androidユーザーは5か月間オンライ...