画像はBaotu.comより メッセージ キューは主に、アプリケーションの結合、非同期処理、トラフィックのクリッピングなどの問題を解決します。現在、最も一般的に使用されているメッセージ キューには、RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMQ などがあります。 Redis、MySQL、phxsql などの一部のデータベースでも、メッセージ キューの機能を実現できます。 実際のアプリケーション シナリオにおけるメッセージ キュー:
今日は、Kafka の典型的な設計分析記事を皆さんと共有したいと思います。 Confluent によると、トップのメッセージング ミドルウェアとして、Fortune 500 企業の 3 分の 1 以上が Apache Kafka を使用しています。 Kafka はパフォーマンスが速く、スループットが高く、他のメッセージ キューよりも高いレベルにあります。メッセージ量が多い場合でも高いパフォーマンスを維持できます。インターネット企業の間で非常に人気があります。皆さんが Kafka の設計の基本原則を理解していただければ幸いです。 Kafka アーキテクチャ Kafka は非常によく設計されたものです。それだけです。ここで言う「細心の注意」とは、特定の標準を完全に実装するという意味ではありません。 逆に、JMS などの課題を完了した学生のように、Kafka は JMS などの規範の制約を打ち破ります。素晴らしい、また別の JMS です。 私がテクノロジーを「まだ…」と呼ぶとき、それはそのテクノロジーが私の視野に入ってきたことを意味します。さて、今度はカフカとストームの時間です。この記事ではまず Kafka について説明します。 Kafka とは何ですか?公式ドキュメントを参照してください。これは Apache プロジェクトです。メッセージキューです。 メッセージ キューの仕組み: メッセージ キューは、プロデューサーとコンシューマーの間のメッセンジャーであり、両者間の直接的な接触を回避します。 実際には、キャッシュと同じ役割を果たし、生産者と消費者の間の代謝率の差を平滑化しますが、その基本的な目的は生産者と消費者を切り離すことです。少しわかりにくいように思われるかもしれませんが、簡単に説明させてください。 簡単に言えば、撃って忘れる、本物の男は爆発を決して見ず、タバコの吸い殻をガソリンタンクに投げ込み、ウインドブレーカーの襟を立て、ズボンのポケットに手を入れ、振り返らずに立ち去る。 このようなリアルな人間を生み出すのが、Message Queue(以下、MQ)です。これにより、プロデューサーは MQ にメッセージをスローしてそのままにしておくことができ、コンシューマーはプロデューサーと対話することなく MQ からメッセージを取得できるようになります。 以降のセクションでは、Kafka のプロトタイプを私なりの方法で徐々に進化させていきます。全体的な文脈を把握するためには、多くの詳細が必然的に隠されることになります。 もちろん、これらの詳細は公式文書や他の人のブログで簡単に見つけることができます。私の目的は、同様のシステムを設計するときに参照できるように、コンテキストを整理することです。 MQの「正しい」方向への進化カフカは必ずしも正しいのでしょうか?客観的に言えば、絶対にそうではないが、それがこの記事の主人公なので、正しいに違いない。 まず、一般的な MQ の最も単純な形式を見てみましょう。一般的に言えば、これは MQ に初めて触れた後の全員に対する課題です。 今、問題があります。メッセージを消費する必要があるコンシューマーが 2 人以上いる場合はどうなりますか?とても簡単です。ブロードキャストするだけです: 消費者は神様であり、彼らと付き合うのは非常に難しいことです。あなたが彼らに押し付けるものすべてが、彼らが望んでいるものであるとは限りません。一部だけ欲しい場合はどうなりますか? まあ、消費者はサービスの質の悪さを MQ のせいにしているに違いない。しかし、MQ の何が問題なのでしょうか?メッセージのセマンティクスを理解しません。このような難しい消費者に直面して、企業は生産者にメッセージを細分化するよう求めるしかありません。したがって、複数のトピックが表示されます。 これは非常に明白なアイデアで、メッセージがキューに入力されたときにメッセージのトピックを区別し、コンシューマーがメッセージ キューから興味のあるメッセージを取得できるようにするというものです。 ただし、複数のコンシューマーが同じトピック メッセージに関心を持つ可能性がある状況が依然として存在します。 ブロードキャストを使用する場合、冗長な送信の問題は依然として残ります。ユニキャストを使用する場合、コンシューマーがメッセージを取得した後、メッセージを削除する必要がありますか?削除された場合、他の消費者はどうすればよいですか?ブロードキャストすると帯域幅が浪費されますが、ブロードキャストしないという選択肢もありません... これは悪循環に陥っているようで、この問題は根本から解決されなければならない。明らかなアイデアは次の解決策です (少なくとも、私が自分で設計する場合はそうします)。 問題は解決しましたが、以前のアーキテクチャを注意深く考えて簡単な図を描くと、事態が制御不能になることがわかります。 MQ 自体のロジックは複雑すぎます。 UNIX の哲学に戻ると、新しい問題に遭遇したときは、既存のプログラムに機能を追加するのではなく、新しいプログラムを作成します。 このような観点から、この複雑な問題を消費者に全面的に任せてみてはいかがでしょうか? カフカ寄りですね。 MQ 内のすべてのデータが永続的に保存される場合、消費者は必要なものだけを取得できないのでしょうか? これは根本的な変化です。以前のやり方は、限られたビジネスセットメニューで、食事は強制され、いらないものは捨てなければならなかったのに対し、現在のやり方は、無制限のビュッフェで、好きなものを取ることができるというものです。 メッセージはコンシューマーによって取得できます。メッセージは常に MQ 内にあり、コンシューマーはいつでも任意のメッセージを取得できます。 コンシューマーは MQ に必要なメッセージを伝えるだけでよいので、メッセージ オフセット パラメータを渡す必要があります。 ただし、ビュッフェにも閉店時間があり、食事時間の制限があるところもあります。これは、Kafka の戦略的ストレージの問題です。詳細についてはドキュメントを参照してください。 簡単に言えば、次の図を見てください。 すべて大丈夫です。そうです、これがカフカのオリジナルモデルです。しかし、カフカはそれ以上のものです。以下でそれがどのように進化し続けるかを見てみましょう。 クラスタリング、フォールトトレランス現在の状況を見てみましょう: これは、Kafka のような MQ が持つべき論理構造です。しかし、物理的な実装の面ではどのように機能するのでしょうか? カフカは流通のために生まれたとよく言われます。これをどう理解すればよいのでしょうか?まず、どのように拡張できるかを理解し、次にその拡張をさまざまなマシンに適用できるかを理解する必要があります。まずは容量拡張について見てみましょう。 高速道路と同様、広深高速道路と聞くと、広州から深センまでの高速道路であることがわかります。これは、これまで説明してきた MQ トピックに似た論理的なステートメントです。 しかし、この高速道路が正確にどのような外観をしており、途中どのようにルートされているかは物理的な現実です。また、すべての道路は複数車線に分割され、並行して使用されます。 厳密に言えば、各車線は、小車線、乗客車線、トラック車線、追い越し車線などに細分化されます。これらすべての車線の車は同じ目的地(同じトピックに属する)に向かっていますが、実際には異なるタイプに細分化されています。 次に示すように、パーティションと呼ばれる概念をレーンと比較してみましょう。 このキーハッシュモジュールに注目してください。これは、車がどの車線に入るかを区別するためのロジックです。 Kafka の用語では、レーンとはパーティションのことです。 同じトピック内でメッセージを配信する場合は、ハッシュ関数を自分で設計する必要があります。ハッシュ関数は、メッセージをどのパーティションに順番に配置するかを決定する分散戦略です。 温州の靴工場のオーナーは、類推や例は良くないと言いましたが、これは技術論文であって技術文書ではなく、主に自分自身が読むものなので、類推はやはり必要です。 トピック ルーティングは、どの高速道路を経由してどこに行くかを決定し、キー ハッシュは、車、バス、またはトラックのどれでそこに行くかを決定します。 Kafka は同じトピックの同じパーティション内のメッセージの順序のみを保証し、グローバルな順序を実現できないことに注意してください。 これは欠陥ではありません。それは両方の長所を兼ね備えたものです。完全な順序にはシリアル化が必要ですが、シリアル化は並列化できないため、まったく意味がありません。 現在、「トピック」の下に「パーティション」という新しいユニットがあります。このパーティションは、Kafka における最も基本的なデプロイメント ユニットです。これはクラスターの編成方法に関係するため、覚えておくことが重要です。 さて、これらのトピックとそのパーティションが 2 台のマシン M1 と M2 にどのように展開されるかを見てみましょう。 上の写真は、それぞれに美しさのある 2 つの花が咲いているところです。さて、今度は消費者についてお話しましょう。 MQ 自体がこれほど細かいレベルにまで進化したという事実に、消費者はどのように対処すべきでしょうか?実は、消費者にも水平展開のニーズがあるのです。コンシューマーがパーティションに対応する場合、対応するトピックはコンシューマーの上位になります。 したがって、問題を解決するために消費者グループの概念を導入する追加レベルが追加されます。 CPU キャッシュから Kafka まで、設計の考え方は同じであり、典型的なオールラウンドなグループ連想構造です。 全体像が描かれたので、次はクラスターの展開を示します。いわゆる Kafka クラスターは、2 つの目的を達成するために、各トピックのパーティションを異なるマシンにデプロイすることがわかっています。 1 つはアクセスの並列処理を提供する負荷分散であり、もう 1 つはホット バックアップである高可用性です。これら 2 つの機能を図で示したいと思います。 全体的な構造は次のとおりです。 永続的なストレージ/クエリメカニズム上記の 2 つのセクションでは、Kafka がどのように動作するかを段階的に説明しました。作者がどのように設計したかはわかりませんが、私だったら間違いなく上記のアイデアに従います... 前述の説明は結局のところ概要に過ぎず、あまり満足のいくものではありません。このセクションでは、Kafka ストレージの概要をもう少し詳しく説明します。 MQ 自体の複雑さを軽減し、真にステートレスな設計を実現するために、Kafka は状態維持メカニズムの責任を完全にコンシューマーに移行していることがわかっています。 したがって、メッセージを取得する問題は、コンシューマーがオフセット インデックスを使用して Kafka ストレージからメッセージを取得するというパフォーマンスに関わる問題に変換されます。しかし、どうすればもっと早く確認できるのでしょうか?どうやって? まず最も単純なシナリオを示しましょう。 Kafka の各パーティションが完全で独立したファイルであると仮定すると、このファイルが非常に大きい場合、実際に非常に大きくなります (T レベルまたは P レベルに達することもあります...)。 したがって、大きなファイルから特定のメッセージを取得すること自体が面倒な作業であり、そのファイルがまだディスク上にあると、さらに状況は悪くなります。ディスクのランダムな読み取りと書き込みは難しい問題であり、シーケンシャルな読み取りと書き込みもそれほど良くないことは誰もが知っています。私たちは何をすべきでしょうか? トラバーサル?各パーティションが独立したファイルである場合、トラバースできるのは次の場合のみです。 このトラバーサル問題に直面した場合、一般的な解決策はインデックスを作成し、インデックス データをメモリ内に保持することです。多くのデータベースがこれを実行しており、Kafka でも間違いなく同じことができます。 Kafka の優れた点は、特別なファイル システムに依存せず、データが通常のファイルに保存されることです。 ただし、パーティションを同じサイズの一連の小さなファイルに分割するため、物理的には完全なパーティション ファイルは存在せず、パーティションはディレクトリとしてのみ表示されます。 ファイルシステムは、同じサイズの複数のファイルを管理するのに非常に便利であることはわかっています。 上記の例では、パーティションは 100M のファイルに分割されています。このような小さなファイルはセグメントと呼ばれます。 Kafka に保存する場合、各セグメント ファイルはいっぱいになるまで開かれます。メッセージの長さは必ずしも均一ではないため、各小さなセグメント ファイルに含まれるメッセージの数は必ずしも同じではありません。 しかし、いずれにしても、各セグメント ファイルの最初と最後のメッセージ オフセットを抽出し、それをメタデータとして保存するのは 1 回限りのことであり、これにより常駐メモリ インデックスの確立が容易になります。 この間隔検索ツリーにより、特定のセグメント ファイルをすばやく見つけることができますが、話はそこで終わりません。 Kafka では、各パーティション セグメント ファイルにインデックス ファイルが装備されています。このファイルは何に使用されますか?これは、次の図に示すように、セグメント ファイル内のメッセージのスパース インデックスです。 最後に、2 回の区間ツリー検索の後、最大 1 回の単純なトラバーサルでオフセットの配置を完了できます。 確かに、最終的なトラバーサルは必要かもしれませんが、Kafka は長いセグメントの時間のかかるトラバーサル計算を可能な限り回避し、トラバーサルを非常に小さなレベルに圧縮します。これはトレードオフです!トレードオフは誰ですか?セグメント ファイル内のすべてのメッセージのインデックスを作成しないのはなぜですか? とても簡単です。すべてのインデックスを確立すると、インデックスが非常に大きくなります。メモリ内に常駐させたい場合、メモリ使用量が非常に多くなります。これはまさに時間と空間のトレードオフです。 スパースインデックスチャットスパースインデックスは非常に便利です。この記事で紹介した Kafka セグメント インデックスのスパース インデックスに加えて、さらに 2 つの一般的な例があります (私はアプリケーション プログラマーではなく、カーネル ネットワーク プロトコル スタックに携わっているため、Kafka はあまり一般的ではないと思います)。 メモリ アドレス空間全体をインデックスするには、スパース メソッドでページングを行います。つまり、メモリをメモリ ページと呼ばれる同じサイズのブロックに規則的に分割し、これらのメモリ ページにインデックスを付けます。アドレス テーブルの代わりにページ テーブルを使用して、インデックスをまばらに作成し、インデックスのサイズを削減します。 さらに、IP アドレスは地理的にクラスター化されるため、ルーターの物理デバイスの場合、インターフェイスの送信方向ごとに設定された IP アドレスは、大幅にクラスター化される可能性があります。 ルーティング テーブルは当初、アドレス分類を使用していましたが、後にプレフィックス マッチングを採用してスパース インデックスを作成しました。アドレス分類は、ページのサイズが 1 つではなく複数ある点を除いて、メモリ アドレス ページングに少し似ています。 ここでのアドレス プレフィックスは、Kafka で使用される 2 つのインデックスに似ています。 1 つ目は、規則的なセグメント インデックスであり、2 つ目は、不規則なメッセージ インデックスです。メッセージの長さが固定されていないためです。 2 つの声明は次のように要約されます。 OS メモリ ページ テーブル: 仮想アドレスから物理アドレスを検索する場合、各アドレスを 1 つずつ検索する必要がありますか? もしこれが本当なら、ページ テーブル エントリなどのメモリ管理がどれだけ消費するか計算したことがありますか?仮想アドレスと物理アドレスは完全に連想的な構造になります。 スパース インデックスを採用すると、4K ページを 1 つだけ配置すればよくなり、メモリ ページ テーブルのメモリ使用量が大幅に削減されます。したがって、より効率的です。 ルーティング テーブル: 各 IP アドレスをルーター デバイスのインターフェイスにマッピングする必要がありますか?これは現実的ではありません。このソリューションは、当初は割り当て機関によるクラスフル アドレスのスパース インデックスに基づいていましたが、後に構造を使用したクラスレス サブネットに基づくプレフィックス係数インデックスを採用し、どちらの場合でもルーティング テーブル エントリの数が大幅に削減されました。 UNIX哲学からの脱却逃げ道はない!なぜ?複雑さだけが作業負荷を反映できるからです。 人々は皆、自分の能力を発揮するために障壁を作り、プログラムを非常に複雑にしたいと思っています。結局のところ、単純なことは誰でもできるし、差別化を図りたいなら、物事を複雑にするしかないのです。 数行の Bash スクリプトで難しいタスクを完了した場合、マネージャーはおそらく、そのトリックは C++ ソリューションとは比較にならない小技だと考えるでしょう。 Python は少し優れていますが、Java はさらに優れています。 4、5年前にプログラミング道場のイベントがありました。トピックの 1 つは、文字列の連結、つまり結合操作でした。当時のマネージャーとホストは、既成のインターフェースを可能な限り使用することを重視していました。しかし… 賞賛されていない優れたミニマリストソリューションは数多くあります。最終的に高く評価されたソリューションの特徴は何かご存知ですか?特徴は複雑さです。 この提案の著者がステージに上がって提案を紹介したとき、彼は「私のデザインは非常にシンプルです...」と言い始めたのを覚えています。しかし、技術的に言えば、それは過剰設計であり、簡単に言えば、気取ったものでした。ホストも明らかに中途半端な人ですね、ハハ。 物事は可能な限り複雑にする必要があります。それが能力の反映です。何かが 2 行で実行できる場合、素晴らしいと見なされるためには 30 行で実行する必要があります。 UNIX の哲学は明らかに私たちには適していません。 著者: Geek Reborn 編集者:タオ・ジアロン 出典: 公開アカウント Geek Rebirth (ID: geek__coding) から転載 |
<<: Alibaba Cloud RDSデータベースは「自動運転」機能を実現するために大幅にアップグレードされました
>>: 中国電信がクラウドコンピューティングに投資し、天一クラウドテクノロジー株式会社を設立
デフォルトでは、Ubuntu は root が直接ログインすることを許可しません。何をするにも so...
これらの概念は非常に一般的ですが、初心者はそれらの違いやつながりを理解できない可能性があります。これ...
はじめに: 2011 年に、多くのネットユーザーから、なぜ私のウェブサイトが Baidu に掲載され...
本日、2017 Oracle Cloud Conference が上海で開幕し、2,500 人を超え...
XENVZ.co.uk は openitc.co.uk (2008 年に英国で登録された会社なので、...
コストパフォーマンスと使いやすさに優れた「オルタナティブクラウド」サービスは、スタートアップ企業や中...
最近、 ASO を使わずにアプリをうまく宣伝できるだろうか? あるいは、ASO を使用する場合、他の...
ウェブサイトを外部から最適化する最も効果的な方法は、外部リンクを公開することです。そして、最も価値の...
ブラックハット SEO は、短期間で成功したいと願う一部のウェブマスターがよく使用する戦術です。検索...
ご存知のとおり、外部リンクはクリックに応じて 2 つのタイプに分けられます。1 つはクリック可能で、...
Hostus の今年のブラックフライデーはこの記事で取り上げます。最新ニュースは次のとおりです。ワシ...
ソフトウェア製品の作成に携わる人なら誰でも、開発ライフサイクルを短縮し、継続的な配信と高品質の製品を...
ロンドン五輪の開幕が近づき、国内のネットメディアの放映権をめぐる一大戦いが終結した。 「私の知る限り...
Linodeはどうですか? linode スウェーデン クラウド サーバーはどうですか? Linod...
21日に「conoha - 日本VPSの簡易レビュー」を書きました。シンガポールの状況がどうなってい...