生産失敗 | Kafka のメッセージ送信が数十秒も遅延する原因は、実は...

生産失敗 | Kafka のメッセージ送信が数十秒も遅延する原因は、実は...

以前、私は「理由は分かっているが、理由は分からない。Kafka がバージョン 2.8 で Zookeeper を「放棄」した理由」という記事で、公式が Zookeeper を放棄することを決定した理由を説明しました。当時、Zookeeper は非常に安定しており、基本的に問題はないだろうと反論する読者もいたことを覚えています。 Double Eleven 期間中に遭遇した問題は、Zookeeper の「脆弱性」を証明しており、Zookeeper の脆弱性は Kafka クラスターに深刻な影響を及ぼすことになります。

1. 断層現象

ダブルイレブンショッピングフェスティバルの期間中、私が担当していた Kafka クラスターの応答時間が 10 ~ 30 秒に急上昇し、メッセージの書き込みに深刻な影響が出ました。

ログ分析により、大規模なパーティションリーダー選挙が行われていたことが判明しました。 __consumer_offsets トピックのパーティションでも、多数のパーティション リーダー選出が実行され、メッセージの送信がほぼ停止し、多数のコンシューマー グループの再バランス調整がトリガーされ、クラスター全体がほぼ麻痺しました。最終的に、根本的な原因が判明しました。ブローカー ノードと Zookeeper 間のセッションがタイムアウトし、多数のパーティションの再選出がトリガーされたのです。

この記事では、この失敗をきっかけに、Kafka における Zookeeper の役割と「犯人」を特定するプロセスを分析します。これがトラブルシューティングのヒントになれば幸いです。

2. ZookeeperはKafkaで重要な役割を果たす

障害分析に入る前に、まず Kafka アーキテクチャ設計における Zookeeper の役割について説明します。

コアコンセプト: Kafka の設計者は Zookeeper の使用に非常に慎重です。つまり、コントローラーの選択とブローカー ノードの障害のリアルタイム検出には Zookeeper に依存する必要がありますが、Zookeeper への依存を可能な限り減らすように努めています。

Zookeeper をベースにしたプログラム開発の場合、通常、Zookeeper 内のディレクトリ レイアウトを確認することで、Zookeeper によって実行される機能がわかります。 Zookeeper における Kafka のストレージ ディレクトリ構造を次の図に示します。

上記の各ノードは、Kafka のコア動作メカニズムに関連付けられています。手がかりを追って探索することができます。この記事では、/brokers ディレクトリのレイアウトと機能に焦点を当てる必要があります。ディレクトリの詳細は次のとおりです。

  • /controller Kafka コントローラーに関する情報。 Kafka コントローラーの選択は Zookeeper に依存します。
  • /brokers/ids/{id} は、永続ノード /brokers/ids の下に多数の一時ノードを作成します。各ノードはブローカー ノードを表します。ノードのコンテンツには、ポート、バージョン、リスニング アドレスなどのブローカーの基本情報が格納されます。
  • /brokers/topics/{トピック}/partitions/{パーティション}/state

Kafka バージョン 2.8 未満では、Kafka のトピック内のルーティング情報は最終的に Zookeeper に保存され、各ブローカー ノードは起動後にデータのコピーをメモリにキャッシュします。 /brokers ノードの各子ノードは特定のトピックを表します。トピックのメタデータには、主にパーティションの数と各パーティションのステータス情報が含まれます。各パーティションのステータス情報には主に次のものが含まれます。

  • controller_epoch 現在のクラスター コントローラーのエポックは、コントローラーの選択回数を示し、コントローラーの「バージョン番号」として理解できます。
  • リーダー 現在のパーティションのリーダーが配置されているブローカー ID。
  • Leader_epoch パーティションの Leader_epoch は、パーティション リーダーが選出される回数を示します。 0 から始まり、パーティション リーダーの選出が発生するたびに 1 ずつ増加します。 Kafka は、レプリカの進行状況を示すために依存関係ウォーターマークに依存する低バージョンによって発生する可能性のあるデータ損失とデータ不整合の問題を解決するために、リーダー エポック メカニズムを導入しています。これについては、後続の記事で詳しく分析します。
  • isr パーティションの isr セット。
  • version には、状態パーティション状態データ構造のバージョン番号が格納されます。このフィールドは無視できます。

Zookeeper にも同様の「設計パターン」があり、これは Zookeeper 内に一時的なノード + イベント監視メカニズムを作成して、データのリアルタイムの動的認識を実現するというものです。 /brokers/ids を例に挙げます。

  • Kafka ブローカー プロセスが起動すると、Zookeeper に一時ノード /brokers/ids/{id} が作成されます。ここで、id はブローカー番号です。
  • Kafkaブローカープロセスが停止すると、ブローカーとZookeeper間のセッションがタイムアウトすると、作成された一時ノードが自動的に削除され、ノード削除イベントが生成されます。
  • Kafka コントローラーは、/brokers/ids ディレクトリ内のノードの追加および削除イベントを自動的に監視します。ブローカーがオフラインまたはオンラインになると、コントローラーはそれをリアルタイムで認識し、必要なアクションを実行します。

上記の予備的な紹介の後でも、Kafka は依然として Zookeeper に大きく依存しており、特に Kafka コントローラーの選択とブローカー ノードの生存ステータスはすべて Zookeeper に依存しています。

Kafka コントローラーは、Kafka クラスター全体の「頭脳」です。それが変化すれば、その影響の範囲と程度は想像できる。次の障害分析により、より直感的なプレゼンテーションが可能になります。

注意: この記事は主に障害分析のプロセスについて説明しています。 Kafka コントローラーの選出方法と leader_epoch レプリカ同期メカニズムに関する以降の情報は、「Kafka の原則と実践」コラムで紹介されます。どうぞお楽しみに。

3. 問題分析

メッセージを送信する際の応答時間が長いことに気づいたとき、私の最初の反応は、スレッド スタックをチェックして、ロック ブロックがないかどうかを確認することでした。しかし、スレッド スタックを確認したところ、Kafka がリクエストを処理するために使用するスレッド プールのほとんどが取得タスクでブロックされており、「実行する作業がない」状態になっていることがわかりました。

これは、クライアントのメッセージ送信要求が Kafka のキューに到達しておらず、ネットワークの読み取りと書き込みの処理専用のスレッド プールもアイドル状態であることを意味します。何故ですか?

メッセージ送信側のレイテンシは非常に高いですが、サーバー スレッドは非常にアイドル状態です。これはちょっと変ですか?

サーバー ログの確認を続けると、多数のトピック (システム トピック __consumer_offsets トピックでもリーダー選出が行われていました) が見つかりました。ログは次のとおりです。

コア ログ: リーダー エポックから開始 多数のパーティションがリーダー選挙を実行しています。

Kafka では、リーダー パーティションのみが読み取りおよび書き込み要求を処理できます。フォロワー パーティションは、リーダー パーティションからデータをコピーし、リーダー ノードがクラッシュした後にリーダーの選出に参加するだけです。そのため、リーダー選出中にパーティションはクライアントの書き込み要求を処理できず、送信側には再試行メカニズムがあるため、メッセージ送信の遅延が非常に大きくなります。

では、どのような状況で大量のトピックが再選されるのでしょうか?

現在のクラスターのコントローラー ノードを見つけて state-change.log を確認すると、次のログが見つかります。

多数のパーティションのステータスが OnlinePartition から OfflinePartition に変更されました。

ヒント: ログに従って、ソース コードを確認し、これらのメソッドの呼び出しチェーンを見つけて、対象のログを見つけることができます。

引き続き、Controller ノードの下の controller.log を確認し、重要なログを見つけます。

コアログの解釈:

  • [コントローラー id=1] 8 のブローカー失敗コールバック (kafka.controller.KafkaController) コントローラーはオンライン クラスターからノード 8 を削除しました。コントローラーはなぜノード 8 を削除したのですか?

次に、手がかりに従って、以下に示すようにノード 8 のログを確認します。

コア ログの解釈: ブローカーと Zookeeper 間のセッションがタイムアウトし、一時ノードが削除されたことが判明しました。

セッションがタイムアウトする理由を調べる前に、まずセッション タイムアウトが Kafka クラスターに与える重大な影響について見てみましょう。

/brokers/ids の下のノードが削除された場合、Kafka コントローラーはそれを適時に取得し、対応する処理を実行できます。

ここで考慮すべき状況が 2 つあります。

3.1 通常のブローカーノードは削除される

処理エントリは、KafkaController の onBrokerFailure メソッドです。コードの詳細は次の図に示されています。

通常のブローカーが zk から削除されると、Kafka コントローラーはノードに割り当てられたすべてのパーティションのステータスを OnlinePartition から OfflinePartition に変更し、パーティションの再選択をトリガーします。

拡張知識ポイント: __consumer_offsets パーティションがリーダーを再選出すると、多数のコンシューマー グループが再バランスをトリガーします。その背後にあるメカニズムは次のとおりです。

コンシューマー グループは、ブローカー側でグループ コーディネーターを選出する必要があります。選出アルゴリズムは次のとおりです。コンシューマ グループ名のハッシュコードはトピック __consumer_offsets のキューの合計数を法として計算され、残りは __consumer_offsets パーティションにマップされます。パーティションのリーダーが配置されているブローカー ノードは、コンシューマー グループのグループ コーディネーターとして機能します。

パーティションのリーダーが変更されると、対応するコンシューマ グループは、コンシューマ グループの再バランス調整をトリガーするために、新しいグループ コーディネーターを再選択する必要があります。

3.2 コントローラノードが削除される

Zookeeper から削除されたブローカー ID が Kafka コントローラーである場合、影響はさらに大きくなります。メインエントリは次の図に示されています。

コントローラー ノードのセッションがタイムアウトすると、一時ノード/コントローラー ノードが削除され、Kafka コントローラーの選択がトリガーされます。最終的には、すべてのブローカー ノードが、ノード/コントローラーの削除、追加、またはノード データの変更に関する通知を受信します。 KafkaController の onControllerFailover メソッドが実行され、Zookeeper 関連のイベント リスナーが再登録され、パーティション ステート マシンとレプリカ ステート マシンが停止して再起動され、各パーティションで自動リーダー パーティション選出がトリガーされます。

それは、新しい皇帝、新しい大臣、そしてすべてがまた始まる、と説明することができます。

3.3 Zookeeperセッションタイムアウトの根本原因のトラブルシューティング

サーバー ログを確認すると、次のログが表示されます。

コア ログの解釈: クライアントのソケット接続が閉じられました... 接続がクライアントによってアクティブに閉じられたことを示します。

では、なぜクライアントはハートビートを積極的にオフにするのでしょうか?ハートビート処理のルーチンでは、クライアントは定期的にハートビート パケットをサーバーに送信する必要があります。サーバーが指定された時間内にハートビート パケットを受信または処理しない場合は、タイムアウトになります。

調べる唯一の方法はソースコードを読むことです。 Zookeeper クライアントのソース コードを調べたところ、次のような設計があることがわかりました。クライアントはまずすべてのリクエストをキューに入れ、次に送信スレッド (SendThread) を介してキューからリクエストを取得し、サーバーに送信します。キーコードは次のとおりです。

zk 更新操作が多数ある場合、ハートビート パケットが時間内に処理されない可能性があります。 Zookeeper セッション タイムアウトが発生する前に、クラスターは ISR の広い領域で拡大および縮小し、zk を頻繁に更新するため、クライアント ハートビート タイムアウトが発生します。この問題は、次のコードでも再現できます。

この一連の分析の結果、Zookeeper セッション タイムアウトによるメッセージ送信の大幅な遅延とコンシューマー グループの大規模な再調整の根本的な原因が判明しました。これで今回の共有は終了です。また次回お会いしましょう。

<<:  Kubernetes クラスタ ロギングの基本を簡単に説明します

>>:  Oracle のキーワードの解釈: データ、イノベーション、オープンな協力

推薦する

基礎知識:分散SQLとは何か

[51CTO.com クイック翻訳] 過去 40 年近くにわたって、SQL はリレーショナル データ...

ハイブリッド クラウドの概念実証を成功させるための 4 つのステップ

ハイブリッド クラウドの概念実証は、展開が IT およびビジネスのニーズを完全に満たしていることを確...

Alibaba Cloud エコシステムがインテリジェントな「ナビゲーションの時代」を切り開く

業界が成長すると、Alibaba Cloud はエコシステムを構築します。業界がエコシステムを構築し...

王涛:Jiuxian.com の Baidu 入札最適化の分析

Jiuxian.com、Goujiu.com、Hongjiuke.comなどのワイン販売ウェブサイト...

#推奨# UK2 - 年間支払い 12 ポンド/無料の com ドメイン名/無料の SSL/cPanel パネル/10 の Web サイトを構築

UK2 グループの子会社である UK2.NET (1998 年から運営) には、年間支払いがわずか ...

5Gとエッジコンピューティングを組み合わせる利点は何ですか?

速度の向上とレイテンシの短縮は、5G とエッジ コンピューティングの組み合わせが今日非常に人気となっ...

BaiduとGoogleのスパイダークローラーを誘惑しよう

私は起業家情報ネットワークの編集者です。今日は、スパイダーを誘惑して、ウェブサイトのコンテンツとスナ...

エッジが従来のデータセンターを補完する方法

ビジネスが成長するにつれて、コンピューティング インフラストラクチャの拡大によって障害のリスク ポイ...

moonvmはどうですか?台湾アポルダイナミックVPSレビュー

moonvmはどうですか? moonvm 台湾アポルはどうですか? moonvm は、台湾の hin...

トラフィックを飛ばして、Baidu News Sourceに参加する役割と方法について話す

Baidu News Searchは最近、検索結果の表示スタイルだけでなく、表示される検索結果の数に...

ウェブサイトの包含の削減を内部から科学的に分析

ウェブサイトのインクルージョンは、すべての基礎です。インクルージョンがなければ、何も語れませんので、...

一度限りの消費ユーザーを維持する方法

インターネット上のさまざまな業界のウェブサイトの中には、消費者が2度目を購入することがほとんどない業...

Apple iCloudがハッキングされる

海外メディアの報道によると、ハッカーらが欧米のオタクが集まるフォーラム「4chan」でハリウッド女優...

「SEO in Plain Language」の10日間の解釈

この本を書く目的は、お金を稼ぐためでも、皆さんと学び、コミュニケーションをとるためでもありません。私...