Unclean Leader Election(以下、ULE)は、ISR内に生存レプリカがない非常時に、OSRからもリーダーを選出して可用性を回復する仕組みです。その代償は、未複製レコードの巻き戻し(データ損失)です。
本稿では、ULEの挙動、データ損失のメカニズム、設定判断の基準、関連パラメータとの組み合わせ、監視・演習、そしてCCAAKで問われやすい観点を、実務に即して整理します。Kafkaの公式ドキュメントと整合する安定概念を前提に説明します。
Kafkaの各パーティションはリーダーとフォロワーで構成され、十分に同期したレプリカの集合がISR(in-sync replicas)です。通常のリーダー選出はISRからのみ行われるため、整合性が守られます。
ULEは、障害でISR内に生存レプリカが1つもない場合でも、OSR(out-of-sync replicas)からリーダーを選出し、パーティションをオンラインに戻します。デフォルトは無効(false)で、無効時はISR復帰までパーティションはオフラインのままです。
障害時の選挙パス(ISRが全滅したケース)
パーティション P (RF=3)
初期状態:
R1(Leader) R2(Follower) R3(Follower)
ISR = {R1, R2} OSR = {R3}
障害発生: R1ダウン、R2も同時障害
生存: R3のみ(ただしOSR)
分岐:
1) ULE=false(デフォルト)
-> リーダー不在のまま待機
-> パーティションPは一時オフライン
-> ISR回復後に通常の選挙
2) ULE=true
-> OSRのR3を暫定リーダーに選出
-> 旧R1にだけあった未複製レコードは失われる(ロールバック)
-> 可用性は回復するが履歴は不連続になり得る関連プロパティ(ブローカー既定とトピック上書き)
# broker(server.properties あるいは動的設定)
unclean.leader.election.enable=false # 推奨デフォルト
# トピック単位で例外的に有効化(避難ログ等)
# Kafka (kafka-configs.sh)
kafka-configs.sh --bootstrap-server <broker:9092> \
--alter --topic critical-telemetry \
--add-config unclean.leader.election.enable=true
# 有効値の確認
kafka-configs.sh --bootstrap-server <broker:9092> \
--describe --topic critical-telemetry | grep uncleanULEは「ISR内に生存レプリカが存在しない」かつ「生存するOSRがいる」状況でのみ意味を持ちます。無効の場合はパーティションが一時的にオフラインとなり、クライアントにはNotLeaderOrFollowerやLEADER_NOT_AVAILABLEに類するエラーが返り得ます。
有効の場合、コントローラはOSRから新リーダーを選びます。旧リーダーから新リーダーへ完全には複製されていないレコードは、新リーダーのログには存在しないため、旧リーダーが復帰した際にリーダーエポックおよび高水位(HW)に従ってトランケーションが行われ、結果的に当該レコードは履歴から消えます。acks=1で受領されていた書き込みは失われる可能性があります。acks=allかつmin.insync.replicasを適切に設定していれば、その条件を満たした書き込みは原理的にロスしませんが、条件未達の書き込みはACKされずに失敗として返るため、アプリ側で再試行設計が必要です。
コントローラ/ブローカーのログ例(要点のみ)
[Controller] Partition P: No live ISR; unclean leader election is enabled
[Controller] Electing new leader from OSR: R3, new leader epoch=42
[Broker R3] Became leader for P-0 at epoch 42
[Broker R1] Truncating log for P-0 from offset 105 down to HW 102 (on recovery)金融勘定やオーダーイベントのように履歴一貫性が最重要なトピックでは、ULEは基本的に無効のままにし、RF≥3、min.insync.replicas≥2、プロデューサはacks=allを徹底します。ダウンタイムは許容し、誤差のない履歴を守ります。
逆に、短時間の欠落が業務に致命的でない観測・テレメトリ系では、SLAに応じて一部トピックでULEを有効化する判断があり得ます。この場合も、min.insync.replicasとacksの整合、アラート、再送ロジックの設計を合わせて行います。
| 設定パターン | 可用性(障害時) | データ損失リスク/プロデューサ挙動 |
|---|---|---|
| ULE=false(デフォルト) | 低い(ISR復帰まで当該パーティションは停止) | 損失リスクは最小。acks=all+minISR満たす書き込みは堅牢。未達は失敗で返る。 |
| ULE=true | 高い(OSRから即時選挙で継続) | 未複製の末尾がロールバックし得る。acks=1のACK済みでも失われ得る。 |
| ULE=true + min.insync.replicas=2 + acks=all | 高い(継続可能) | 条件を満たした書き込みは安全だが、条件未達は失敗で返る。過去のacks=1書き込みは失われ得る。 |
| RF=1(どちらでも) | 単一ブローカーに依存 | レプリケーションがないためULE以前に単点障害でデータ喪失。推奨せず。 |
判断を反映する例(決済=厳格 / テレメトリ=可用性優先)
# 決済トピック(厳格)
kafka-topics.sh --bootstrap-server <broker:9092> --alter --topic payments \
--config unclean.leader.election.enable=false \
--config min.insync.replicas=2
# プロデューサは acks=all を必須化
# テレメトリ(可用性優先)
kafka-topics.sh --bootstrap-server <broker:9092> --alter --topic telemetry \
--config unclean.leader.election.enable=true \
--config min.insync.replicas=2
# ただし未達はアプリ側で再送・欠落許容の前提設計を行う監査から始めます。ブローカー既定とトピック個別の双方を点検し、期待と不整合がないか確認します。変更は可能ならトピック単位で最小限に行うのが安全です(広域既定の変更は影響が大きい)。
動的設定の変更はローリングリスタート不要ですが、既存のクライアントSLAや再試行戦略と矛盾しないか、ステージングで障害注入(ブローカー停止)をして検証します。
設定監査と変更の具体例
# ブローカー既定(ランタイムの動的設定も含む)
kafka-configs.sh --bootstrap-server <broker:9092> --entity-type brokers --entity-name 0 --describe
# (クラスタ全体を見たい場合は各ブローカー、または--allや外部CMDBを使用)
# トピックの有効値
kafka-configs.sh --bootstrap-server <broker:9092> --describe --topic <topic>
# 既定値の変更(慎重に)
kafka-configs.sh --bootstrap-server <broker:9092> --entity-type brokers --entity-name 0 \
--alter --add-config unclean.leader.election.enable=false
# トピック単位の上書き
kafka-configs.sh --bootstrap-server <broker:9092> --alter --topic <topic> \
--add-config unclean.leader.election.enable=true
# 期待するmin.insync.replicasと合わせて設定
kafka-topics.sh --bootstrap-server <broker:9092> --alter --topic <topic> \
--config min.insync.replicas=2ULEの有無に関わらず、障害時に何が起きたかを即座に把握できるメトリクスとログの整備が重要です。特にオフラインパーティション数、ISRの縮退/回復、レイテンシ/エラー率を監視します。
演習では、ステージング環境でブローカーを計画停止し、ULEの有効/無効それぞれでプロデュース/コンシュームの失敗/成功パターン、ログのトランケーション発生有無を確認します。
簡易演習レシピ(ステージングでのみ実施)
# 準備:テストトピック(RF=3, minISR=2)
kafka-topics.sh --bootstrap-server <broker:9092> --create --topic t_ule_test \
--partitions 3 --replication-factor 3 \
--config min.insync.replicas=2 \
--config unclean.leader.election.enable=<true|false>
# プロデュース(acks=all)
kcat -b <broker:9092> -t t_ule_test -P -X acks=all -l msgs.txt &
# ブローカー2台を順に停止(ISRを枯渇させる)
systemctl stop kafka@<brokerA>
systemctl stop kafka@<brokerB>
# 観測
kafka-topics.sh --bootstrap-server <broker:9092> --describe --topic t_ule_test | grep Leader
# JMX/メトリクス: OfflinePartitionsCount, IsrShrinksPerSec を確認
# ログに Truncating が出るか(ULE=true)/パーティション停止(ULE=false)を確認CCAAKでは、ULEの定義、デフォルト、データ損失の条件、min.insync.replicasやacksとの関係が頻出です。特に「acks=allなら常に安全」という誤解を突く設問に注意してください。条件を満たさない状況(ISR不足)では、ACKされずに失敗させることが安全動作であり、ULEを有効化すると履歴が巻き戻る可能性がある、という関係を整理して覚えます。
また、Preferred Leader Election(健全な候補間の優先リーダー切替)と、Unclean Leader Election(OSRからの非常時選出)を混同させる設問もあります。前者は整合性を崩しませんが、後者はデータ損失の可能性があります。
覚えておくCLI断片
# ULEのトピック上書き
kafka-configs.sh --bootstrap-server <broker:9092> --alter --topic <t> \
--add-config unclean.leader.election.enable=true
# min.insync.replicas の設定
kafka-topics.sh --bootstrap-server <broker:9092> --alter --topic <t> \
--config min.insync.replicas=2
# Preferred Leader Election(別概念、整合性は維持)
kafka-preferred-replica-election.sh --bootstrap-server <broker:9092>CCAAK
問題 1
クラスタの一部障害で、あるパーティションのISR内に生存レプリカがなくなった。ダウンタイムを避けるためにunclean.leader.election.enable=trueを当該トピックに設定すると、どの結果が最も正確か?(プロデューサはacks=1で稼働中)
正解: A
ULE有効時はOSRからの選出が行われ、旧リーダーのみが保持していた未複製データはトランケーションで失われ得ます。acks=1は損失を防ぎません。ULE無効時はISR回復までオフラインのままです。
ULEを有効化すればプロデューサのエラーは減りますか?
障害直後の可用性は上がり、ACK返却率が一時的に上がる可能性はあります。ただし未複製分の履歴がロールバックし得るため、アプリの整合性要件によっては致命的です。acks=allとmin.insync.replicasの設計を先に見直してください。
トランザクション(EOS)とULEの併用は安全ですか?
推奨されません。トランザクションマーカーや末尾レコードが未複製のままULEでOSRへ切替わると、復旧時にトランケーションが発生し、整合性が崩れます。トランザクションを使うトピックではULEは無効にし、RF≥3・min.insync.replicas≥2・acks=allを前提に運用してください。
中間解として“しばらく待ってから”ULEする方法はありますか?
Kafka自体にはその待機ウィンドウを直接制御する一般的な設定はありません。実務では、ULEは原則無効とし、復旧時間短縮(監視・自動復帰・迅速なブローカー再起動)、十分なRF、適切なmin.insync.replicas、クライアントのリトライ/バックオフ設計で代替します。ULEを使う場合は、対象トピックを限定し、演習で影響範囲を把握しておくことが重要です。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Kafka Topic と Partition の基礎: 分散とスケーラビリティの要
CCDAK 対策と実務の両立を意識し、Topic/Partition/Replica/Consumer Group の役...
CCDAK 試験ガイド:出題範囲・配点・申込み・対策
Confluent Certified Developer for Apache Kafka (CCDAK) の出題範囲...
Confluent Certified Administrator (CCAAK) 対策: 出題範囲・配点の考え方・運用観点の要点
CCAAKに向けて、試験領域の押さえどころを運用目線で整理。プロダクションで通用する設定・監視・セキュリティの実践知を、...
Kafka の Replica と In-Sync Replicas を正しく設計する: 耐障害性と一貫性
レプリカとISRの仕組みを起点に、acks と min.insync.replicas、クリーン/アンクリーンリーダー選...
Kafka の Offset とコミット: ポジション管理と at-least-once の基礎
CCDAK 対策と実務の両立を意識して、Kafka コンシューマのオフセット管理とコミット戦略を整理。at-least-...