Kafkaレプリケーション設定:データ耐久性と可用性の確保
分散システムの領域では、データの耐久性と高可用性が最重要課題です。主要な分散イベントストリーミングプラットフォームであるKafkaは、堅牢なレプリケーションメカニズムを通じてこれらの重要な特性を実現しています。Kafkaのレプリケーションを理解し、正しく設定することは、ブローカー障害に耐え、継続的な運用を維持できる、弾力性と信頼性の高いデータパイプラインを構築するための基本です。
この記事では、Kafkaのレプリケーション戦略を深く掘り下げ、データが複数のブローカー間でどのようにコピーされ、維持されるかの背後にある核となる概念を説明します。In-Sync レプリカ (ISR) の役割、リーダー選出のメカニズム、そしてこれらの要素がどのように集合的にフォールトトレランスに貢献するかを探ります。さらに、ブローカーレベルとトピックレベルの両方でレプリケーションを設定するための実践的なガイダンスと、データの安全性とアクセシビリティを保証するためのベストプラクティスを提供します。
このガイドを読み終えることで、Kafkaレプリケーションに関する包括的な理解が得られ、予期せぬ障害に直面した場合でも、最適なデータ耐久性と高可用性を実現するようにクラスターを設定できるようになります。
Kafkaレプリケーションの基礎を理解する
Kafkaのアーキテクチャは、スケーラビリティと並列処理のためにパーティションの概念に依存しています。これらのパーティション内のデータが失われず、ブローカーが故障した場合でもアクセス可能であることを保証するために、Kafkaはレプリケーションを採用しています。各パーティションには、クラスター内の異なるブローカーに分散された複数のコピー、つまりレプリカがあります。
レプリカとパーティション
各パーティションには、2種類のレプリカがあります。
- リーダーレプリカ: 各パーティションには1つのレプリカがリーダーとして指定されます。リーダーはそのパーティションに対するすべての読み取りおよび書き込みリクエストを処理します。プロデューサーは常にリーダーに書き込み、コンシューマーは通常リーダーから読み取ります。
- フォロワーレプリカ: パーティションの他のすべてのレプリカはフォロワーです。フォロワーは、それぞれのパーティションリーダーからデータをパッシブにレプリケートします。彼らの主な役割は、リーダーが失敗した場合に引き継ぐ準備ができているバックアップとして機能することです。
レプリケーションファクター
レプリケーションファクターは、Kafkaクラスター全体に存在するパーティションのコピー数を定義します。たとえば、レプリケーションファクターが3の場合、各パーティションには1つのリーダーと2つのフォロワーレプリカが存在することを意味します。レプリケーションファクターが高いほど、耐久性と可用性は向上しますが、ディスクスペースとネットワーク帯域幅も多く消費します。
In-Sync レプリカ (ISR)
In-Sync レプリカ (ISR) は、Kafkaの耐久性保証にとって重要な概念です。ISRは、リーダーに完全に追いついており、「同期している」と見なされるレプリカ(リーダーまたはフォロワーのいずれか)です。Kafkaは、各パーティションのISRのリストを維持します。このリストは次の理由で重要です。
- 耐久性: プロデューサーが確認応答 (
acks) をall(または-1) に設定してメッセージを送信する場合、書き込みが成功したと見なされる前に、すべてのISRによってメッセージがコミットされるまで待機します。これにより、メッセージが複数のブローカーに耐久性のある形で書き込まれることが保証されます。 - 可用性: リーダーブローカーが故障した場合、利用可能なISRの中から新しいリーダーが選出されます。すべてのISRが最新のデータを保持していることが保証されているため、このセットから新しいリーダーを選出することでデータ損失がないことが保証されます。
フォロワーレプリカは、処理が遅い、データのフェッチを停止する、またはクラッシュした場合に同期が外れる可能性があります。Kafkaはこれを監視し、フォロワーがリーダーからあまりにも遅れている場合(replica.lag.time.max.msで制御)、ISRリストから削除されます。追いつくと、ISRセットに再参加できます。
リーダー選出:継続的な可用性の確保
パーティションの現在のリーダーレプリカが利用できなくなった場合(例:ブローカーのクラッシュやネットワークの問題による)、Kafkaは自動的にリーダー選出プロセスを開始します。主な目標は、残りのISRの中から新しいリーダーを選出し、パーティションが読み書きのために利用可能な状態を維持することです。
選出プロセスは次のようになります。
- 検出: クラスターコントローラー(コントローラーとして選出されたKafkaブローカーの1つ)がリーダーの障害を検出します。
- 選択: コントローラーは、そのパーティションの残りのISRの1つを新しいリーダーに選択します。すべてのISRは同一の最新データを保持していることが保証されているため、このプロセスはデータの一貫性を維持します。
- 更新: コントローラーは、新しいリーダーに関する情報をクラスター内のすべてのブローカーに通知します。
アンクリーンリーダー選出
Kafkaは、ISRが利用できない場合(例:すべてのISRが同時にクラッシュした場合)のリーダー選出の動作を決定する設定パラメーター unclean.leader.election.enable を提供しています。
unclean.leader.election.enableがfalse(デフォルトで推奨される設定)の場合、ISRが利用できない場合、Kafkaは新しいリーダーを選出しません。これは、非ISRフォロワーを選出するとデータ損失につながる可能性があるため、可用性よりもデータ耐久性を優先します。unclean.leader.election.enableがtrueの場合、Kafkaは、ISRではない、またはコミットされたすべてのメッセージをレプリケートしていない可能性がある利用可能なレプリカから新しいリーダーを選出します。これは、厳密なデータ耐久性よりも可用性を優先し、データ損失のリスクを冒しますが、パーティションが動作可能な状態を維持します。
警告:
unclean.leader.election.enableの有効化は、極めて慎重に行う必要があり、通常は可用性が絶対に重要で、少量のデータ損失のリスクが許容されるシナリオ(例:重要ではない一時的なデータ)でのみ行うべきです。ほとんどの運用システムでは、falseのままにすべきです。
Kafkaレプリケーションの設定
レプリケーション設定は、ブローカーレベル(新しいトピックのデフォルトとして)とトピックレベル(デフォルトを上書きしたり、既存のトピックを変更したりするため)の両方で設定できます。
ブローカーレベルの設定
これらの設定は、各Kafkaブローカーの server.properties ファイルで定義され、明示的なレプリケーション設定なしで作成された新しいトピックのデフォルトとして適用されます。
-
default.replication.factor: 新しいトピックのデフォルトのレプリケーションファクターを設定します。本番環境では、3の値が一般的で、データ損失やダウンタイムなしでn-1(3-1=2) 個のブローカー障害を許容できます。
properties default.replication.factor=3 -
min.insync.replicas: この重要な設定は、acksがall(または-1) に設定されている場合に、プロデューサーがメッセージを正常に書き込むために必要な最小ISR数を定義します。ISRの数がこの値を下回ると、プロデューサーはエラー(例:NotEnoughReplicasException)を受け取ります。これにより、強力な耐久性保証が確保されます。
properties min.insync.replicas=2
> ヒント:min.insync.replicasは通常、(replication.factor / 2) + 1またはreplication.factor - 1に設定すべきです。replication.factor=3の場合、min.insync.replicas=2は、1つのブローカー障害を許容する良いバランスです。 -
num.replica.fetchers: フォロワーブローカーがリーダーからメッセージをフェッチするために使用するスレッドの数。これを増やすと、多くのフォロワーレプリカをホストするブローカーのレプリケーションスループットを向上させることができます。
properties num.replica.fetchers=1
トピックレベルの設定
新しいトピックを作成したり、既存のトピックを変更したりする際に、ブローカーのデフォルトを上書きし、特定のレプリケーション設定を適用できます。
特定のレプリケーション設定でトピックを作成する
kafka-topics.shコマンドラインツールを使用します。
kafka-topics.sh --create --bootstrap-server localhost:9092 \n --topic my_replicated_topic \n --partitions 3 \n --replication-factor 3 \n --config min.insync.replicas=2
この例では、my_replicated_topicは3つのパーティションを持ち、それぞれが3回レプリケートされ、正常な書き込み(acks=allの場合)には少なくとも2つのISRが必要です。
既存のトピックのレプリケーション設定を変更する
一部のトピックレベルのレプリケーション設定を変更できます。既存のトピックのreplication-factorは増やすことができますが、このコマンドを直接使用して減らすことはできません。減らすには、パーティションの手動での再割り当てが必要です。
my_existing_topicのレプリケーションファクターを増やす(例:2から3へ):
kafka-topics.sh --alter --bootstrap-server localhost:9092 \n --topic my_existing_topic \n --replication-factor 3
既存のトピックにmin.insync.replicasを設定する:
kafka-topics.sh --alter --bootstrap-server localhost:9092 \n --topic my_existing_topic \n --config min.insync.replicas=2
注意: レプリケーションファクターを増やすと、Kafkaが既存のデータを新しいレプリカにコピーする自動プロセスがトリガーされます。これは、特に大きなトピックの場合、I/O負荷が高くなる可能性があります。
プロデューサーの保証と確認応答 (acks)
Kafkaプロデューサーのacks(確認応答)設定は、送信されるメッセージの耐久性保証を決定します。これはmin.insync.replicasと連携して機能します。
acks=0: プロデューサーはメッセージをブローカーに送信し、いかなる確認応答も待ちません。これは最も低い耐久性(メッセージ損失の可能性あり)を提供しますが、最高のスループットを実現します。acks=1: プロデューサーは、リーダーレプリカがメッセージを受信し、確認応答するのを待ちます。リーダーがフォロワーがメッセージをレプリケートする前に故障した場合、データ損失が発生する可能性があります。acks=all(またはacks=-1): プロデューサーは、リーダーがメッセージを受信し、かつすべてのISRもメッセージを受信してコミットするのを待ちます。これは最強の耐久性保証を提供します。min.insync.replicasが設定されている場合、プロデューサーは成功を確認する前に、その数のISRがメッセージをコミットするのを待ちます。これは重要なデータに推奨される設定です。
プロデューサー設定例 (Java):
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("acks", "all"); // 最高の耐久性を保証
Producer<String, String> producer = new KafkaProducer<>(props);
// ... メッセージを送信
レプリケーションによるフォールトトレランスの確保
Kafkaレプリケーションは、データ損失やサービス中断なしにブローカー障害に耐えるように設計されています。クラスターが同時に耐えられるブローカー障害の数は、replication.factorおよびmin.insync.replicas設定に直接依存します。
replication.factor=Nのクラスターは、min.insync.replicasが適切に設定されている場合、データ損失なしで最大N-1個のブローカー障害に耐えることができます。replication.factor=3でmin.insync.replicas=2の場合、1つのブローカー(リーダーまたはフォロワーのいずれか)が失われても、完全な機能と耐久性を維持できます。2番目のブローカーが故障すると、ISRの数は1(または最後のフォロワーだった場合は0)に減少し、acks=allのプロデューサーはブロックまたは失敗し、データの安全性を優先します。
ベストプラクティス:ラック認識レプリケーション
特にクラウド環境では、さらなるフォールトトレランスのために、Kafkaブローカーとそのレプリカを異なる物理ラックまたはアベイラビリティゾーンに分散させることを検討してください。Kafkaはラック認識レプリケーションをサポートしており、コントローラーは、単一の物理障害ドメインで複数のレプリカを失う可能性を最小限に抑えるために、パーティションのリーダーレプリカとフォロワーレプリカを異なるラックに分散させようとします。
これを有効にするには、各ブローカーのserver.propertiesでbroker.rackプロパティを設定します。
# ブローカー1のserver.properties
broker.id=1
broker.rack=rack-a
# ブローカー2のserver.properties
broker.id=2
broker.rack=rack-b
# ブローカー3のserver.properties
broker.id=3
broker.rack=rack-a
Kafkaはその後、レプリカを異なるラックに配置するよう努めます。
レプリケーションステータスの監視
Kafkaクラスターのレプリケーションステータスを定期的に監視することは、耐久性や可用性に影響を与える可能性のある問題を事前に特定するために不可欠です。監視すべき主要なメトリクスには次のものがあります。
- UnderReplicatedPartitions: レプリケーションファクターよりも少ないISRを持つパーティションの数。ゼロ以外の値は潜在的な問題を示します。
- OfflinePartitionsCount: アクティブなリーダーを持たないパーティションの数。これは深刻な停止とデータ利用不可を示します。
- LeaderAndIsr/PartitionCount: パーティションごとのリーダーとISRの合計数。
kafka-topics.shコマンドを使用してトピックのレプリケーションステータスを確認できます。
kafka-topics.sh --describe --bootstrap-server localhost:9092 --topic my_replicated_topic
出力例:
Topic: my_replicated_topic PartitionCount: 3 ReplicationFactor: 3 Configs: min.insync.replicas=2
Topic: my_replicated_topic Partition: 0 Leader: 0 Replicas: 0,1,2 Isr: 0,1,2
Topic: my_replicated_topic Partition: 1 Leader: 1 Replicas: 1,2,0 Isr: 1,2,0
Topic: my_replicated_topic Partition: 2 Leader: 2 Replicas: 2,0,1 Isr: 2,0,1
この出力において:
* Leader: 現在パーティションのリーダーであるブローカーID。
* Replicas: このパーティションのレプリカをホストするすべてのブローカーIDのリスト。
* Isr: 現在In-Sync ReplicaセットにあるブローカーIDのリスト。
いずれかのブローカーIDがReplicasには表示されるがIsrには表示されない場合、そのレプリカは同期が外れています。
ベストプラクティスとトラブルシューティングのヒント
replication.factorを賢く選択する: 通常、本番環境では3、重要度の低いデータには2、開発用には1。数値が高いほど耐久性は向上しますが、リソース消費も増加します。min.insync.replicasを設定する: 特にacks=allを使用する場合、耐久性保証が満たされるように常にこれを設定してください。- レプリカを分散する:
broker.rackを使用して、レプリカが異なる物理的な障害ドメインに分散されるようにします。 - 積極的に監視する: KafkaのJMXメトリクスやPrometheus/Grafanaなどのツールを使用して、
UnderReplicatedPartitionsを監視します。 - アンクリーンリーダー選出を避ける: 強力な耐久性保証のために、本番環境では
unclean.leader.election.enableをfalseに設定したままにしてください。 - ブローカーの再起動を処理する: ブローカーを再起動するときは、フォロワーが再同期し、
min.insync.replicasを維持できるように、一度に1つずつ行います。
結論
Kafkaレプリケーションは、そのデータ耐久性と高可用性の礎です。replication.factor、min.insync.replicasを慎重に設定し、プロデューサーのacksがこれらの設定とどのように相互作用するかを理解することで、障害に強く、ストリーミングデータに強力な保証を提供するKafkaクラスターを設計できます。
ラック認識レプリケーションや堅牢な監視などの機能を活用することで、最も要求の厳しい本番環境でも、重要なデータパイプラインが動作し続け、データが安全に保たれることを保証できます。適切に設定されたレプリケーション戦略は単なるオプションではなく、信頼性の高いKafkaデプロイメントには不可欠です。