Kafkaには、同期レプリカセットの概念があります。これは、リーダーからそれほど離れていないノードのセットです。
ネットワークがクリーンにパーティション化され、リーダーを含む少数派が一方の側にあり、多数派がもう一方の側に他の同期ノードを含む場合はどうなりますか?
少数派/リーダー側は、おそらくノードの束を失ったと考えており、それに応じてISRサイズを縮小し、喜んで続行します。
反対側はおそらくリーダーを失ったと思っているので、新しいリーダーを選び、楽しく続けます。
これで、同じクラスターに2つのリーダーがあり、書き込みを個別に受け入れます。大多数のノードがパーティションの後で続行する必要があるシステムでは、古いリーダーはステップダウンして書き込みの受け入れを停止します。
カフカのこの状況ではどうなりますか? ISRセットを変更するには、多数決が必要ですか?もしそうなら、リーダー側が停止を検出するまで、短いデータ損失がありますか?
私はこれをテストしていませんが、受け入れられた答えは間違っており、ラース・フランケは脳分裂の可能性について正しいと思います。
Zookeeperクォーラムには過半数が必要なため、ZKアンサンブルパーティションの場合、最大で片側にクォーラムがあります。
コントローラーになるには、ZK(エフェメラルznode登録)とのアクティブなセッションが必要です。現在のコントローラーがZKクォーラムから離れて分割されている場合、それ自体をコントローラーと見なすことを自発的に停止する必要があります。これには最大でzookeeper.session.timeout.ms = 6000
かかります。まだZKクォーラムに接続しているブローカーは、その中から新しいコントローラーを選択する必要があります。 (これに基づく: https://stackoverflow.com/a/52426734 )
トピックパーティションリーダーになるには、ZKとのアクティブなセッションも必要です。 ZKクォーラムへの接続を失ったリーダーは自発的に1つになるのをやめるべきです。選出されたコントローラーは、一部の元リーダーが欠落していることを検出し、ISRのリーダーから新しいリーダーを割り当て、引き続きZKクォーラムに接続します。
では、ZKタイムアウトウィンドウ中にパーティション化された元リーダーが受信したプロデューサーリクエストはどうなりますか?いくつかの可能性があります。
プロデューサーのacks = all
とトピックのmin.insync.replicas = replication.factor
の場合、すべてのISRはまったく同じデータを持つ必要があります。元リーダーは最終的に進行中の書き込みを拒否し、プロデューサーはそれらを再試行します。新しく選出されたリーダーはデータを失うことはありません。一方、パーティションが修復されるまで、書き込み要求を処理することはできません。クライアントリクエストを拒否するか、しばらくバックグラウンドで再試行し続けるかは、プロデューサー次第です。
そうしないと、新しいリーダーが最大zookeeper.session.timeout.ms + replica.lag.time.max.ms = 16000
相当のレコードを失い、パーティションが修復された後に元のリーダーから切り捨てられる可能性が非常に高くなります。
読み取り専用であることに満足しているよりも長いネットワークパーティションを期待しているとしましょう。
このようなものが機能します:
replication.factor = 3
があり、各アベイラビリティーゾーンに1つのレプリカ、min.insync.replicas = 2
があります。acks = all
このように、ネットワークパーティションのZKクォーラム側に2つのKafka ISRがあり、そのうちの少なくとも1つは元リーダーと完全に最新である必要があります。したがって、ブローカーでのデータ損失はなく、利用可能です。勝者側に接続できるプロデューサーからの書き込み用。
Kafkaクラスターでは、ブローカーの1つがコントローラーとして機能するように選択されます。
とりわけ、コントローラーは新しいリーダーを選出する責任があります。レプリカ管理セクションでは、これについて簡単に説明します。 http://kafka.Apache.org/documentation/#design_replicamanagment
Kafkaは、Zookeeperを使用して、一度に1つのコントローラーのみが存在することを確認しようとします。ただし、説明した状況は依然として発生する可能性があり、Zookeeperアンサンブル(両側にクォーラムがあると仮定)とKafkaクラスターを2に分割し、2つのコントローラーになります。
その場合、Kafkaには、影響を制限するためのいくつかの構成があります。
unclean.leader.election.enable
_:デフォルトではFalseです。これは、同期していないレプリカがリーダーになるのを防ぐために使用されます。使用可能なレプリカが同期していない場合、Kafkaはパーティションをオフラインとしてマークし、データの損失を防ぎますreplication.factor
_と_min.insync.replicas
_:たとえば、それぞれ3と2に設定すると、「スプリットブレイン」の場合、プロデューサーが_acks=all
_クラスターが元に戻った後に分岐したログの処理の詳細については、 KIP-101 も参照してください。