Kafkaの保持設定は、可用性や再処理性だけでなく、ディスク/クラウドのコストを直撃します。特にCCAAK(Confluent認定 Kafka 管理者)では、retention.ms・retention.bytes・cleanup.policyの正しい組み合わせと、セグメント削除の実際の挙動理解が頻出です。
本稿は公式ドキュメントの動作に忠実に、時間ベース・サイズベース・compactionの設計指針と、運用コストの見積もり手順をまとめます。試験対策の要点と、現場で迷わない具体策を両立させています。
Kafkaの保持はパーティションのセグメントファイル単位で評価されます。アクティブなセグメントは削除対象になりません。セグメントは log.segment.bytes(サイズ満了)または log.roll.ms/hours(時間満了)でローテーションされ、非アクティブになって初めて保持評価の対象になります。
cleanup.policy=deleteのとき、保持は2つの条件で発火します。時間ベース(retention.ms)により「古い」セグメントの削除、またはサイズベース(retention.bytes)により「総サイズ超過時に最古から間引き」。どちらかの条件に該当すれば削除が進みます。チェック間隔は log.retention.check.interval.ms で制御されます。
パーティションとセグメント、保持評価のイメージ
公式に沿った基本設定例(サーバー既定とトピック上書き)
# broker側(server.properties の一例)
log.retention.check.interval.ms=300000
log.segment.bytes=1073741824 # 1 GiB
log.retention.ms=604800000 # 7日(トピック未設定時の既定)
# トピック作成時に上書き(時間ベース保持)
$ kafka-topics.sh \
--create --topic orders \
--partitions 6 --replication-factor 3 \
--config retention.ms=259200000 # 3日
# 後からサイズベースへ切替(片方のみでも可)
$ kafka-configs.sh --alter --entity-type topics --entity-name orders \
--add-config retention.bytes=21474836480 # 20 GiB/partition
--delete-config retention.ms # 時間保持を無効化retention.ms は再処理・追いつきの猶予をダイレクトに表現できます。コンシューマ遅延や障害復旧時間、下流バッチの再実行ウィンドウが明確な場合に適しています。セグメントの最終更新時刻と比較して閾値を過ぎると、非アクティブセグメントから削除されます。
注意点は、トラフィックが薄いとセグメントがロールされずアクティブのまま長期間残ることです。この場合、log.roll.ms を設定して時間で強制ロールすると想定どおりに削除が進みます。
時間ベース保持とセグメント強制ロール
$ kafka-configs.sh --alter --entity-type topics --entity-name audit_log \
--add-config retention.ms=1209600000 # 14日
--add-config min.insync.replicas=2
# アクティブ維持を避けるため、ブローカでの強制ロール例
log.roll.ms=21600000 # 6時間ごとにロール(サーバー再起動で反映)retention.bytes は各パーティションの合計ログサイズ上限を定め、超過時に最古の非アクティブセグメントから削除します。トラフィックが変動しても使用ディスクを上限に抑えられるため、容量計画や請求額のコントロールに向きます。
ただし、スパイクで短期的に新規データが急増すると、古いデータが想定より早く消える可能性があります。再処理の最低保証期間がある場合は、retention.ms と併用せず、十分なバッファを含めた retention.bytes を設定するか、監視とアラートで補完します。
サイズベース保持の指定例と確認
$ kafka-configs.sh --alter --entity-type topics --entity-name events \
--add-config retention.bytes=32212254720 # 30 GiB/partition
# 現在の設定を確認
$ kafka-configs.sh --describe --entity-type topics --entity-name events | grep retention
retention.bytes=32212254720 sensitive=false synonyms={DYNAMIC_TOPIC_CONFIG:32212254720}cleanup.policy=delete は到達不能になったセグメントを丸ごと削除します。一方、cleanup.policy=compact はキー重複を圧縮し、最新のキーのみを残します。状態同期やCDCログでは compact が有効ですが、過去履歴が必要なら delete 併用を検討します(compact,delete)。
compaction時の墓石(null値)は delete.retention.ms を過ぎるまで保持されます。これが短すぎると遅延したコンシューマが削除イベントを見逃す可能性があります。compact と delete を併用する場合、時間保持で早期削除されないよう、retention.ms とセグメントロールの兼ね合いに注意します。
| 保持種別 | 主な用途 | 削除/圧縮のトリガ | 代表的設定 |
|---|---|---|---|
| delete(時間) | 再処理猶予を保証 | retention.ms 経過で古いセグメント削除 | retention.ms, log.roll.ms |
| delete(サイズ) | コスト上限の固定 | 合計サイズが retention.bytes 超過で最古から削除 | retention.bytes, log.segment.bytes |
| compact | 最新状態の保持(CDC/状態同報) | ログクリーナがキー重複を圧縮、墓石は delete.retention.ms 後除去 | cleanup.policy=compact, delete.retention.ms, min.cleanable.dirty.ratio |
| compact,delete | 最新状態+有限履歴 | 圧縮+時間/サイズの両方 | cleanup.policy=compact,delete + retention.* |
compact,delete 併用の安全な最小構成例
$ kafka-configs.sh --alter --entity-type topics --entity-name users_kv \
--add-config cleanup.policy=compact,delete \
--add-config delete.retention.ms=604800000 \
--add-config min.cleanable.dirty.ratio=0.2 \
--add-config retention.ms=1209600000 # 14日(履歴の上限)オンプレの場合はディスク、クラウドサービスではディスク相当+オブジェクトストレージ(ティアードストレージ採用時)の課金を考慮します。概算は、平均スループット、保持期間(またはサイズ上限)、レプリケーション係数、圧縮率で決まります。
サイズ保持の場合は上限がコストの天井になります。時間保持の場合は期間を変数に試算し、ピークトラフィックとヘッドルーム(例: 30%)を必ず含めます。セグメントはアクティブ中は削除不可で一時的に上ぶれるため、監視と容量アラートのしきい値も含めて設計します。
概算の手計算スクリプト(bash, bc)
# 入力: 50 MB/s、圧縮後係数0.5、保持3日、RF=3、ヘッドルーム30%
IN_MBPS=50
COMP=0.5
RET_DAYS=3
RF=3
HEAD=0.3
BYTES_PER_SEC=$(echo "$IN_MBPS*1024*1024" | bc)
EFFECTIVE=$(echo "$BYTES_PER_SEC*$COMP" | bc)
SECONDS=$(echo "$RET_DAYS*24*3600" | bc)
RAW=$(echo "$EFFECTIVE*$SECONDS*$RF" | bc)
TOTAL=$(echo "$RAW*(1+$HEAD)" | bc)
echo "Required bytes: $TOTAL"削除は即時ではありません。log.retention.check.interval.ms の粒度と、セグメントが非アクティブになるタイミングに依存します。ディスク逼迫の直前に設定変更しても、効果が出るまで遅れることがあります。容量アラートは余裕を持って発報させ、古いセグメントの強制ロールで削除を進めます。
監視ではパーティションごとの LogSize、ブローカーディスク使用率、UnderReplicatedPartitions、コンシューマ遅延を合わせて見ると、保持設定とSLAの齟齬を早期に検知できます。compaction利用時は cleaner のスループットと遅延を継続観測します。
運用時に役立つクイック確認コマンド
# ブローカのログディレクトリ使用量(例)
$ du -sh /kafka-logs/*
# トピック別の総サイズ(概算)。JMXやツール併用が推奨
$ kafka-log-dirs.sh --describe --bootstrap-server <broker:9092> \
--describe-config --topic-list orders
# 重要メトリクス(例):
# kafka.log:type=Log,name=Size,topic=<t>,partition=<p>
# kafka.server:type=ReplicaManager,name=UnderReplicatedPartitionsCCAAK
問題 1
高スパイクが時折発生するイベントトピックでコスト上限を厳守したい。一方で最低48時間の再処理猶予は必要。最も適切な保持設計はどれか。
正解: A
スパイクにより時間保持のみではディスクが溢れる恐れがあるため、サイズ上限でコストを固定するのが前提。ただし最低48時間の再処理猶予を満たすには、平常時だけでなくスパイク時の一時的な上振れも含めて retention.bytes を見積もる必要がある。Cはチェック間隔を短くしても上限を厳しくすると48時間保証が崩れる可能性が高い。Bはコスト上限を制御できない。Dは履歴保持要件を満たさない。
時間とサイズを同時に設定したらどうなる?
どちらの条件でも削除が発火します。総サイズが上限を超えれば最古から削除、時間が経過していれば古いセグメントが削除されます。いずれもアクティブセグメントは対象外です。
削除が進まないのはなぜ?
アクティブセグメントのままでロールされていない、log.retention.check.interval.ms が長い、セグメントの最終更新時刻が保持閾値を超えていない、あるいはブローカのクリーンアップ処理が遅延している可能性があります。log.roll.ms の設定や監視で状況を確認してください。
compactionと時間保持を併用すると何に注意?
墓石(null値)を delete.retention.ms の間は保持する必要があります。これが短いと遅延したコンシューマが削除を取りこぼします。retention.ms により早期にセグメントごと消えて墓石が流れ切らないケースもあるため、セグメントロールと各タイマーの整合を取ってください。
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-...