この記事はWeChatの公開アカウント「JavaKeeper」から転載したもので、著者は実在の人物です。この記事を転載する場合はJavaKeeper公式アカウントまでご連絡ください。 Kafka を MQ として使用する場合でも、ストレージ層として使用する場合でも、機能は 2 つだけです (非常にシンプルに見えます)。 1 つは、プロデューサーによって生成されたデータがブローカーに保存されることであり、もう 1 つは、コンシューマーがブローカーからデータを読み取ることです。 Kafka の速度は、読み取りと書き込みの 2 つの側面に反映されます。 Kafka が高速である理由についてお話ししましょう。 1. パーティションを使用して並列処理を実現する Kafka が Pub-Sub メッセージング システムであることは誰もが知っています。公開またはサブスクライブのいずれの場合でも、トピックを指定する必要があります。 トピックは単なる論理的な概念です。各トピックには 1 つ以上のパーティションが含まれ、異なるパーティションは異なるノードに配置できます。 一方、異なるパーティションを異なるマシンに配置できるため、クラスターの利点を最大限に活用してマシン間の並列処理を実現できます。一方、パーティションは物理的にフォルダに対応しているため、同一ノード上に複数のパーティションが存在する場合でも、同一ノード上の異なるパーティションを異なるディスクに配置するように構成することができ、ディスク間の並列処理を実現し、複数ディスクの利点を最大限に発揮することができます。 並列処理が可能であれば、速度は確実に向上し、1 人のワーカーよりも複数のワーカーの方が確実に高速に動作します。 「異なるディスクに並行して書き込むことはできますか?ディスクの読み取りと書き込みの速度を制御できますか?」 まず、ディスク/IO について簡単に説明しましょう。 「ハードディスクのパフォーマンスを制限する要因は何ですか?ディスクのI/O特性に基づいてシステムを設計するにはどうすればよいですか?」ハードディスク内の主なコンポーネントは、ディスクプラッター、トランスミッションアーム、読み取り/書き込みヘッド、およびスピンドルモーターです。実際のデータはディスクに書き込まれ、読み取りと書き込みは主にトランスミッションアームの読み取り/書き込みヘッドによって行われます。実際の操作中、スピンドルはディスクプラッターを回転させ、次にトランスミッションアームを伸ばして読み取りヘッドがディスクを読み書きできるようにします。ディスクの物理構造を下図に示します。 単一のディスクの容量には限りがあるため、ハードディスクには通常 2 つ以上のディスクが搭載されています。各ディスクには 2 つの面があり、どちらにも情報を記録できるため、1 つのディスクは 2 つのヘッドに対応します。ディスクは多数のセクター形の領域に分割されており、各領域はセクターと呼ばれます。ディスクの中心を中心としてディスク表面にある異なる半径の同心円をトラックと呼び、異なるディスク上の同じ半径のトラックで構成された円筒をシリンダと呼びます。トラックとシリンダーはどちらも、異なる半径の円を表します。多くの場合、トラックとシリンダーは互換的に使用できます。ディスク プラッターの垂直ビューを次の図に示します。 画像ソース: commons.wikimedia.org ディスクに影響を与える主な要因はディスク サービス時間、つまりディスクが I/O 要求を完了するのにかかる時間であり、これはシーク時間、回転遅延、およびデータ転送時間の 3 つの部分で構成されます。機械式ハードドライブの連続読み取りおよび書き込みパフォーマンスは非常に優れていますが、ランダム読み取りおよび書き込みパフォーマンスは非常に劣ります。これは主に、ヘッドが正しいトラックに移動するのに時間がかかるためです。ランダム読み取りおよび書き込み中は、ヘッドを継続的に移動する必要があり、ヘッドのアドレス指定に時間が浪費されるため、パフォーマンスは高くありません。ディスク パフォーマンスを測定するための主な重要な指標は、IOPS とスループットです。 Kafka や HBase などの多くのオープンソース フレームワークでは、追加書き込みを通じてランダム I/O を可能な限りシーケンシャル I/O に変換し、アドレス指定時間と回転遅延を削減して IOPS を最大化します。興味のある学生はディスクI/O[1]をご覧ください。 ディスクの読み取りと書き込みの速度は、ディスクの使用方法、つまり、順次読み取りと書き込みか、ランダム読み取りと書き込みかによって異なります。 2. ディスクへの順次書き込み 画像ソース: kafka.apache.org Kafka の各パーティションは順序付けられた不変のメッセージ シーケンスであり、新しいメッセージはパーティションの末尾に継続的に追加され、順次書き込みが行われます。 「かなり前に誰かがベンチマークをしました: 1 秒あたり 200 万回の書き込み (3 台の安価なマシンで) http://ifeve.com/benchmarking-apache-kafka-2-million-writes-second-three-cheap-machines/ ディスク容量が限られているため、すべてのデータを保存することはできません。実際、メッセージング システムとして、Kafka はすべてのデータを保存する必要はなく、古いデータを削除する必要があります。順次書き込みのため、Kafka がさまざまな削除戦略を使用してデータを削除する場合、「読み取り/書き込み」モードを使用してファイルを変更するのではなく、パーティションを複数のセグメントに分割し、各セグメントが物理ファイルに対応し、ファイル全体を削除することでパーティション内のデータを削除します。この方法は古いデータをクリアし、ファイルへのランダム書き込み操作を回避します。 3. ページキャッシュを最大限に活用する キャッシュ層を導入する目的は、Linux オペレーティングシステムのディスクアクセスのパフォーマンスを向上させることです。キャッシュ層は、ディスク上のデータの一部をメモリにキャッシュします。データ要求が到着すると、データがキャッシュ内に存在し、最新のものであれば、データはユーザープログラムに直接渡され、基盤となるディスクの操作が排除され、パフォーマンスが向上します。キャッシュ層は、ディスク IOPS が 200 を超える主な理由の 1 つでもあります。Linux 実装では、ファイル キャッシュは 2 つのレベルに分かれており、1 つはページ キャッシュ、もう 1 つはバッファー キャッシュです。各ページ キャッシュには、複数のバッファー キャッシュが含まれています。ページ キャッシュは主に、プロセスがファイルに対して読み取り/書き込み操作を行うときに、ファイル システム上のファイル データのキャッシュとして使用されます。バッファー キャッシュは主に、システムがブロック デバイスを読み書きするときに、ブロック上のデータをキャッシュするためにシステムによって使用されるように設計されています。 ページキャッシュを使用する利点:
ブローカーはデータを受信した後、ディスクに書き込むときにデータをページ キャッシュに書き込むだけで、データが完全にディスクに書き込まれることは保証しません。この観点から、マシンがクラッシュすると、ページ キャッシュ内のデータがディスクに書き込まれず、データが失われる可能性があります。ただし、このような損失は、停電などによりオペレーティング システムが動作を停止した場合にのみ発生し、このシナリオは Kafka レベルのレプリケーション メカニズムによって完全に解決できます。このような状況でデータが失われないようにするために、ページ キャッシュ内のデータを強制的にディスクにフラッシュすると、実際にはパフォーマンスが低下します。このため、Kafka ではページ キャッシュ内のデータを強制的にディスクにフラッシュするための flush.messages および flush.ms パラメータが提供されていますが、Kafka ではこれらの使用は推奨されていません。 4. ゼロコピー技術 Kafka には、ネットワーク データをディスクに保存するプロセス (プロデューサーからブローカー) と、ディスク ファイルをネットワーク経由で送信するプロセス (ブローカーからコンシューマー) が多数あります。このプロセスのパフォーマンスは、Kafka の全体的なスループットに直接影響します。 「オペレーティングシステムの中核はカーネルです。カーネルは通常のアプリケーションから独立しており、保護されたメモリ空間にアクセスでき、基盤となるハードウェアデバイスにアクセスできます。ユーザープロセスがカーネルを直接操作するのを防ぎ、カーネルのセキュリティを確保するために、オペレーティングシステムは仮想メモリをカーネル空間 (Kernel-space) とユーザー空間 (User-space) の 2 つの部分に分割します。」 従来の Linux システムでは、標準 I/O インターフェイス (読み取りや書き込みなど) はデータ コピー操作に基づいています。つまり、I/O 操作により、カーネル アドレス空間のバッファーとユーザー アドレス空間のバッファー間でデータがコピーされるため、標準 I/O はキャッシュ I/O とも呼ばれます。これを行う利点は、要求されたデータがすでにカーネルのキャッシュ メモリに格納されている場合、実際の I/O 操作を削減できることですが、欠点は、データのコピー プロセスによって CPU オーバーヘッドが発生することです。 Kafkaの生成と消費を次の2つのプロセスに簡略化します[2]。
4.1 ディスクへのネットワークデータの永続化(プロデューサーからブローカーへ) 従来のモードでは、ネットワークからファイルへのデータ転送には、4 つのデータ コピー、4 つのコンテキスト スイッチ、および 2 つのシステム コールが必要です。
このプロセスには、実際には 4 つのデータ コピーが含まれます。
「DMA (ダイレクト メモリ アクセス): ダイレクト メモリ アクセス。DMA は、CPU を介さずに周辺機器とシステム メモリ間の双方向データ転送を可能にするハードウェア メカニズムです。DMA を使用すると、システム CPU を実際の I/O データ転送プロセスから解放できるため、システム スループットが大幅に向上します。 同時に、次の図に示すように、4つのコンテキストスイッチがあります。 データ ストレージは通常リアルタイムではなく、Kafka プロデューサー データの永続性についても同様です。 Kafka のデータはハードディスクにリアルタイムで書き込まれません。これは、最新のオペレーティング システムのページング ストレージを最大限に活用してメモリを使用し、I/O 効率を向上させます。これが、前のセクションで説明したページ キャッシュです。 Kafka の場合、プロデューサーによって生成されたデータはブローカーに保存されます。このプロセスは、ソケット バッファーからネットワーク データを読み取り、実際にはカーネル空間で直接ディスクに書き込むことができます。ソケット バッファーのネットワーク データをアプリケーション プロセス バッファーに読み込む必要はありません。ここで、アプリケーション プロセス バッファは実際にはブローカーであり、ブローカーは永続化のためにプロデューサーからデータを受信します。 この特別なシナリオでは、ソケット バッファーからネットワーク データを受信するときに、アプリケーション プロセスは中間処理を必要とせず、それを直接保持します。 mmap メモリ ファイル マッピングを使用できます。 「メモリ マップ ファイル: mmap と略され、MMFile とも呼ばれます。mmap を使用する目的は、カーネル読み取りバッファのアドレスをユーザー空間バッファにマップすることです。これにより、カーネル バッファをアプリケーション メモリと共有できるようになり、カーネル読み取りバッファからユーザー バッファにデータをコピーするプロセスが不要になります。その動作原理は、オペレーティング システムのページを直接使用して、ファイルを物理メモリに直接マッピングすることです。マッピングが完了すると、物理メモリでの操作がハード ディスクに同期されます。この方法を使用すると、I/O が大幅に改善され、ユーザー空間からカーネル空間へのコピーのコストが節約されます。 Mmap にも明らかな欠陥があり、信頼性が低いのです。 mmap に書き込まれたデータは、実際にはハードディスクに書き込まれません。オペレーティング システムは、プログラムがアクティブにフラッシュを呼び出したときにのみ、データをハード ディスクに書き込みます。 Kafka は、アクティブにフラッシュするかどうかを制御するためのパラメーター producer.type を提供します。 Kafka が mmap に書き込んだ直後にフラッシュして Producer に戻る場合、それは同期 (sync) と呼ばれます。 Kafka が flush を呼び出さずに mmap に書き込んだ直後に Producer に戻る場合、それは非同期 (async) と呼ばれ、デフォルトは sync です。 ゼロコピー テクノロジーとは、コンピューターが操作を実行するときに、CPU が最初に 1 つのメモリ領域から別のメモリ領域にデータをコピーする必要がないため、コンテキストの切り替えと CPU のコピー時間が短縮されることを意味します。その機能は、ネットワーク デバイスからユーザー プログラム空間へのデータグラム転送プロセスにおけるデータ コピーとシステム コールの数を減らし、CPU の関与をゼロにし、この点での CPU 負荷を完全に排除することです。現在、ゼロコピー技術には主に3つの種類があります[3]。
4.2 ディスクファイルはネットワーク経由で送信されます(ブローカーからコンシューマーへ) 従来の実装: 最初にディスクを読み取り、次にソケットを使用して送信します。実際には 4 つのコピーが関係します。
このプロセスは、上記の制作メッセージと比較できます。
Linux 2.4 以降のカーネルは、sendfile システム コールを介してゼロコピーを提供します。データは DMA 経由でカーネル バッファーにコピーされた後、CPU コピーを必要とせずに DMA 経由で NIC バッファーに直接コピーされます。これはゼロコピーという用語の由来でもあります。データのコピーが削減されるだけでなく、ファイルの読み取りからネットワークへの送信まですべてが sendfile 呼び出しで完了するため、プロセス全体でコンテキスト スイッチが 2 回しか発生せず、パフォーマンスが大幅に向上します。 ここで Kafka が採用したソリューションは、NIO の transferTo/transferFrom を介してオペレーティング システムの sendfile を呼び出すことによってゼロ コピーを実装することです。合計2回のカーネルデータコピー、2回のコンテキストスイッチ、1回のシステムコールが発生し、CPUデータコピーが排除されます。 5. バッチ処理 多くの場合、システムのボトルネックとなるのは CPU やディスクではなく、ネットワーク IO です。 したがって、オペレーティング システムによって提供される低レベルのバッチ処理に加えて、Kafka クライアントとブローカーは、データをネットワーク経由で送信する前に、複数のレコード (読み取りと書き込みの両方) をバッチで蓄積します。レコードをバッチ処理すると、より大きなパケットが使用されるため、ネットワークの往復コストが削減され、帯域幅の使用率が向上します。 6. データ圧縮 プロデューサーはデータを圧縮してブローカーに送信し、ネットワークの転送コストを削減できます。現在サポートされている圧縮アルゴリズムは、Snappy、Gzip、LZ4 です。データ圧縮は通常、最適化ツールとしてバッチ処理と組み合わせて使用されます。 概要 |次に面接官にKafkaがなぜ速いのかと聞かれたら、こう答えよう。
参考文献 [1] Meituan - ディスクI/Oについて: https://tech.meituan.com/2017/05/19/about-desk-io.html [2] Kafkaゼロコピー: https://zhuanlan.zhihu.com/p/78335525 [3] Linux - ゼロコピー: https://cllc.fun/2020/03/18/linux-zero-copy/ |
<<: [高同時実行性] 数十億のトラフィック下で分散電流制限を実現するにはどうすればよいでしょうか?これらの理論をマスターしなければなりません! !
1. Macvlan の紹介Macvlan が登場する前は、イーサネット カードには複数の IP ア...
arkecxはどうですか? Zenlayer直系のクラウドサーバーブランドとして、期待が高まっている...
まず、Baidu スナップショットについて理解しましょう。Baidu は、インターネット上で検索が許...
米国最大のオンライン小売業者であるアマゾンは、世界各地で電子商取引サイトを促進する戦略の一環として、...
少し前、Weibo が WeChat に取って代わられるという噂がありました。事実はそうではないこと...
WebFaction は現在、ホスティング製品に使用できる 50 ドルのクレジットをお客様のアカウン...
私たち SEO 担当者にとって、ブログを立ち上げることは最も一般的なことです。私たちはほぼ毎日、さま...
著者 |趙雲37Signals(プロジェクト管理プラットフォームBasecamp)のCTO、Davi...
最近、多くのウェブマスターがイライラし、落ち込んでいます。一生懸命更新した記事をサイトに公開した後、...
2018年3月にミニプログラム広告が社内テスト用に正式に公開され、すべてのカテゴリーのミニプログラム...
Dog は、MIT の Sep Kamvar、Salman Ahmad、Zahan Malkani ...
【編集者注】この記事の翻訳者は@小轰同学です。この記事では、ワイヤーフレーム、プロトタイプ、モックア...
Baidu Webmaster Platform LEE の「外部リンク判定について」を解釈し、スパ...
ウェブサイト攻撃やトロイの木馬は、ウェブサイトのランキングが消える原因の 1 つであり、最も一般的な...
短編動画が流行する前は、ライブストリーミングが最もホットなトレンドでした。当時は生放送が絶対的な主役...