退屈です。3日2泊して、ようやくカフカの内部構造がわかりました。以前にたくさんの記事を読んだのですが、はっきりしていませんでしたが、まだはっきりとした構図が頭にありませんでした...
1.カフカの紹介
Apache Kafkaは、もともとLinkedInによってオープンソース化された分散メッセージングシステムでしたが、現在はApacheのサブプロジェクトであり、オープンソース分野で最も広く使用されているメッセージングシステムの1つになっています。Kafkaコミュニティは非常に活発です。バージョン0.9以降、Kafkaのスローガンは「高スループットの分散メッセージングシステム」から「分散ストリーミングプラットフォーム」に変更されました。
Kafkaは、次の点で従来のメッセージングシステムとは異なります。
- Kafkaは、スケールアウトが容易な分散システムです。
- パブリッシュとサブスクライブの両方に高いスループットを提供します
- 複数のサブスクライバーをサポートし、障害が発生したときに自動的にコンシューマーのバランスを取ります
- 消息的持久化
2.カフカコア組成
上に示したように、プロデューサー、ブローカー、トピック、パーティション、コンシューマーグループ、コンシューマー、およびその他のコンポーネントを確認できます。
Kafkaアーキテクチャのセットには、複数のプロデューサー、複数のブローカー、および複数のコンシューマーがあります。各プロデューサーは複数のトピックに対応でき、各コンシューマーは1つのコンシューマーグループにのみ対応できます。
成分 | 前書き |
---|---|
プロデューサー | メッセージプロデューサー:ブローカーにメッセージを送信するクライアント |
プロデューサー | メッセージコンシューマー:ブローカーからメッセージを読み取るクライアント |
ブローカ | 中間メッセージ処理ノード:Kafkaノードはブローカーです。1つ以上のブローカーがKafkaクラスターを形成できます(通常、奇数のクラスターが推奨されます。少なくとも3つ)。 |
トピック | トピック:Kafkaクラスターに公開される各メッセージはトピックを指定する必要があり、Kafkaメッセージはトピックに保存されます |
パーティション | パーティション:物理ストレージの概念。トピックは複数のパーティションに分割できます。各パーティションは内部的に順序付けられていますが、複数のパーティションによって結合されたデータは順序付けられていません。 |
消費者グループ | コンシューマーグループ:各コンシューマーは特定のコンシューマーグループ(CG)に属し、メッセージは複数の異なるCGに送信できますが、同じパーティションのデータはCG内の1人のコンシューマーのみが消費できます。 |
いくつかのコンポーネントのより詳細な説明は次のとおりです。
2.0動物園の飼育係
動物園の飼育係(選挙、バランス、メタ記録、消費記録を担当)
Zookeeperは、クラスター内のブローカーおよびコンシューマーと対話して、データとクラスターの高可用性を維持します。
- 消費者消費メッセージの位置情報を記録します。
- パーティションが失敗したときのリーダー選出
- Kafkaのメタ情報をzookeeperに保存する方法
注:プロデューサーはzkに登録されておらず、コンシューマーはzkに登録されています。
動物園飼育係のkafkaの構造図は次のとおりです。
2.1パーティション(水平拡張、高い同時実行性)
Kafkaは、トピックごとに分散パーティションログファイルを維持し、各パーティションはKafkaストレージレベルの追加ログです。このパーティションに投稿されたメッセージはすべてログファイルの最後に追加されます。パーティション内の各メッセージには、時系列で単調に増加するシーケンス番号が割り当てられます。これは、長い番号であるオフセットです。このオフセットを通じて、パーティション内の一意のメッセージを判別できます。パーティションでは順序が保証されますが、トピックでは順序は保証されません。
上記の表の内容に応じて、各パーティションは内部的に順序付けられていますが、複数のパーティションによって結合されたデータは順序付けられていません
メッセージプロデューサーがメッセージを送信するとき:
- patitionが指定されている場合、そのpatitionは直接使用されます
- patitionは指定されていませんが、キーが指定され、ハッシュはキー値によって実行され、パーティション数の残りは、同じキー値が同じパーティションにルーティングされるように取得されます。強い順序の一貫性が必要な場合キューでは、すべてのメッセージを両方とも同じキーに設定することができます。
- patitionもkeyも指定されていません。ポーリングを使用してpatitionを選択してください
パーティションの理由:
1.クラスター内で水平方向に拡張すると便利です。各パティションは、それが配置されているマシンに適応するように調整でき、トピックは複数のパティションで構成できるため、クラスター全体が任意のサイズのデータに適応できます。
2.パティション単位で読み書きできるため、高い同時実行性を向上させることができます。(複数のリクエストが異なるパターンで配布される場合があります)
2.2コピーメカニズム(高可用性)
上の図では、次のように表示されます。Kafkaクラスター管理メッセージ。このレイヤーには3つのブローカーがあります。その中にはBroker1にTopicAがありますが、このTopicAにはPartition0、Partition1の2つのパーティションがあります。
上記の表で述べたように、トピックには複数のパーティションを含めることができます
ご覧のとおり、Broker2にはTopicAもあり、このTopicAにはPartition0とPartition1の2つのパーティションもあります。
Broker1の場合:Partition0はリーダー、Partition1はフォロワーです
が、Broker2の場合:Partition0はフォロワー、Partition1はリーダーです
Broker2のPartition0をBroker1のPartition0のコピーと呼びます。実際、これらは両方ともコピーと呼ぶことができ、Broker1のPartition0はマスターコピーです。
質問:Partition0のコピーをBroker2に配置するのはなぜですか?
回答:リーダーとフォロワーを同じマシンに配置すると、このマシンがハングアップしたときに、このパーティションのデータがすべてなくなったためではないでしょうか。何のためにコピーが必要ですか?
Kafkaのレプリケーションメカニズムは、複数のサーバーノードが他のノードのトピックパーティションのログをレプリケートすることです。クラスター内のノードに障害が発生すると、障害が発生したノードにアクセスする要求が他の通常のノードに転送され(このプロセスは通常、Reblanceと呼ばれます)、Kafkaの各トピックの各パーティションにはマスターコピーと0個以上のレプリカがあります。レプリカはデータをマスターレプリカと同期させたままにし、マスターレプリカに障害が発生すると置き換えられます。
同じパティションに複数のレプリケーションが含まれる場合があります(server.properties構成ファイルのdefault.replication.factor = Nに対応)。レプリケーションがないと、ブローカーがダウンすると、パターン上のすべてのデータを消費できなくなり、プロデューサーはパターン上のデータを保存できなくなります。レプリケーションの導入後、同じパティションに複数のレプリケーションがある場合があります。現時点では、これらのレプリケーションからリーダーを選択する必要があります。プロデューサーとコンシューマーはこのリーダーとのみ対話し、他のレプリケーションはフォロワーとして機能してリーダーからデータをコピーします。 。
Kafkaでは、すべてのレプリカを使用してプライマリレプリカを置き換えることができるわけではないため、ISR(同期レプリカ)セットは、同期セットとも呼ばれるKafkaのリーダーノードで維持されます。このセットの必要性2つの条件は次のとおりです。会った:
- ノードはZKに接続されたままである必要があります
- 同期プロセス中、このコピーはマスターコピーから大きく遅れることはありません。
ISRは、次のようにすべてのコピーが存在する場所を格納します。[0,2,1]、この構造ストレージと同様に、0、2、1はブローカーIDを表します(このIDは一意です)
[0,2、1 ]:現在のリーダーがID 0、2、1のマシン上にあることを示します。これは、他の2つのコピーが配置されているマシンを意味します。
注:実際、2が1の前にあることは不合理ではありません。つまり、 ID 2のマシンコピーはマスターコピーにさらに近く、リーダーが電話を切ると、2が新しいリーダーとして選出されます。
質問:Kafkaがブローカーよりも多いレプリカの数を設定すると、エラーが報告されます。
解決策:前述のように、Kafkaのコピーは異なるブローカーに保存されます。コピーの数がブローカーの数よりも多い場合、現時点では同じブローカーのコピーが少なくとも2つあるとしたら、ポイントは何ですか。
2.3高性能ログストレージ
Kafkaのトピックの下にあるすべてのメッセージは、パーティション方式で複数のノードに分散および保存されます。同時に、Kafkaマシンでは、各パーティションは実際にはログディレクトリに対応しており、ディレクトリの下には複数のログセグメント(LogSegment)があります。LogSegmentファイルは、「。index」ファイルと「.log」ファイルの2つの部分で構成され、それぞれセグメントインデックスファイルとデータファイルとして表されます。これら2つのファイルのコマンドルールは次のとおりです。パーティショングローバルの最初のセグメントは0から始まり、後続の各セグメントファイルには、前のセグメントファイルの最後のメッセージのオフセット値という名前が付けられ、値のサイズは64ビット、長さは次のように、番号の20ビットです。1000個のメッセージがあり、各LogSegmentサイズが100であると仮定すると、番号は0で埋められません。以下は、900〜1000のインデックスとログを示しています。
Kafkaのメッセージデータは大きすぎるため、すべてのインデックスを作成すると、スペースを取り、時間がかかるため、Kafkaはスパースインデックス方式を選択します。これにより、インデックスがメモリに直接入力され、部分的なクエリ速度が向上します。 。
データの読み取り方法を簡単に紹介します。911データを読み取りたい場合、最初のステップは、それが属するセグメントを見つけ、二分法に従ってそれが属するファイルを見つけることです。0000900.indexと00000900を見つけた後。ログ、次にインデックスに移動して、インデックス(911-900)= 11または11未満の最も近いインデックスを見つけます。ここで、インデックスは二分法によって[10,1367]であることがわかり、これの物理的な位置を渡します。インデックス1367を作成し、911データが見つかるまで後で検索を開始します。
上記は特定のオフセットを探すプロセスに関するものですが、ほとんどの場合、特定のオフセットを見つける必要はなく、順番に読み取る必要があります。読み取る順序で、オペレーティングシステムは間に追加します。メモリとディスクページcaheは、通常見られる先読み操作であるため、順次読み取り操作は非常に高速です。ただし、Kafkaには問題があります。パーティションが多すぎると、ログセグメントが多くなります。書き込みをバッチで実行すると、実際にはランダム書き込みになります。現時点では、ランダムI / Oがパフォーマンスに大きな影響を与えます。したがって、一般的に言って、Kafkaはあまり多くのパーティションを持つことはできません。これに応じて、RocketMQはすべてのログを1つのファイルに書き込み、シーケンシャル書き込みになる可能性があります。特定の最適化により、読み取りはシーケンシャル読み取りに近くなります。
考えてみてください。1。なぜパーティションを作成する必要があるのですか。つまり、トピックにはパーティションが1つしかないのですが、そうではありませんか。2.ログをセグメント化する必要があるのはなぜですか?
1.パーティションは水平展開用です。2。同じファイル内のログが大きすぎると、パフォーマンスに影響します。ログが無期限に大きくなると、クエリ速度が遅くなります
3.消費モデル
メッセージがプロデューサーによってKafkaクラスターに送信された後、コンシューマーによって消費されます。一般的に、消費モデルにはプッシュとプルの2種類があります。
プッシュモデルのメッセージシステムに基づいて、メッセージエージェントは消費ステータスを記録します。メッセージエージェントがメッセージをコンシューマーにプッシュした後、メッセージを消費済みとしてマークしますが、このメソッドは消費の処理セマンティクスを適切に保証できません。たとえば、コンシューマーにメッセージを送信すると、ネットワーク上の理由で消費プロセスがハングアップしたり、メッセージが受信されなかったりします。消費エージェントでメッセージを消費済みとしてマークすると、メッセージは完全に失われます。プロデューサーがメッセージを受信した後にこの返信方法を使用する場合、メッセージエージェントは消費ステータスを記録する必要がありますが、これは望ましくありません。プッシュを使用する場合、メッセージの消費率はコンシューマーエージェントによって完全に制御されます。コンシューマーがブロックされると、問題が発生します。
カフカはプルモデル(ポール)を採用し、消費速度や消費の進行状況を自ら制御し、消費者はオフセットに応じて消費することができます。たとえば、コンシューマーは、再処理のためにすでに消費されているメッセージを消費したり、最近のメッセージを消費したりできます。
プロデューサーがリーダーにデータを送信する場合、データの信頼性レベルはrequest.required.acksパラメーターを介して設定できます:(上の図は-1プロセスの場合です)
-
0:プロデューサーがブローカー同期の完了の確認を待たずに次の(バッチ)メッセージを送信し続け
、遅延が最小になることを意味します。ただし、耐久性が最も低く、サーバーに障害が発生すると、データが失われる可能性があります。たとえば、リーダーが死亡した場合、プロデューサーはそれを知らずにメッセージを送信し続け、データが受信されない場合、ブローカーはデータを失います。 -
1:プロデューサーは、リーダーがデータを正常に受信して確認を取得するのを待ってから、次のメッセージを送信することを意味します。このオプションにより、耐久性が向上し、待ち時間が短縮されます。
パーティションのリーダーが死亡し、フォロワーがコピーされていないため、データが失われます
-
-1:プロデューサーが次のデータを送信する前にフォロワーの確認を取得することを意味します
耐久性は最高で、待ち時間は最悪です。
3つのメカニズムのパフォーマンスが低下し、信頼性が向上しています。
4.ストレージ戦略
メッセージが消費されるかどうかに関係なく、Kafkaはメッセージを保持します。つまり、メッセージは繰り返し消費される可能性があります。
古いデータを削除するには、次の2つの方法があります。
- 時間に基づく:log.retention.hours = 168(構成ファイル内:デフォルトで1週間のデータが保存されます)
- サイズに基づく:log.retention.bytes = 1073741824(1G)
KafkaはO(1)の特定の時間計算量を読み取るため、つまりファイルサイズとは関係がないため、ここで期限切れのファイルを削除しても、Kafkaのパフォーマンスの向上とは関係がないことに注意してください。