Kafka

Kafkaのリテンション設計:時間・サイズ保持とコスト最適化

2026-04-19
NicheeLab編集部

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 で制御されます。

  • 時間保持: retention.ms(トピック単位、ブローカーデフォルトは log.retention.ms)
  • サイズ保持: retention.bytes(パーティション合計サイズの上限)
  • セグメント分割: log.segment.bytes と log.roll.ms/hours
  • 削除の定期評価: log.retention.check.interval.ms
  • compaction関連: cleanup.policy=compact、delete.retention.ms(墓石キー保持期間)、min.cleanable.dirty.ratio など

パーティションとセグメント、保持評価のイメージ

Topic T, Partition p0retention window (time or size)S1S2S3S4 *active最古 → 最初に削除期限/容量超過で削除候補まだ保持内アクティブ (削除不可)・総サイズ > retention.bytes → 最古セグメント(S1,S2…)から削除・セグメント年齢 > retention.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 を設定して時間で強制ロールすると想定どおりに削除が進みます。

  • 向いているケース: 再処理SLOが明確、規制で保管期間が定義されている
  • 要監視: トラフィック薄いトピックは 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 を設定するか、監視とアラートで補完します。

  • 向いているケース: ディスクやクラウド課金を上限管理したい
  • 要注意: アクティブセグメントは削除されないため、過度なスパイク時に一時的な上振れが起きうる
  • 推奨: データ圧縮(producer/compression.type)と適切なセグメントサイズで無駄を抑制

サイズベース保持の指定例と確認

$ 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}

delete と compact の設計比較:併用時の落とし穴も把握する

cleanup.policy=delete は到達不能になったセグメントを丸ごと削除します。一方、cleanup.policy=compact はキー重複を圧縮し、最新のキーのみを残します。状態同期やCDCログでは compact が有効ですが、過去履歴が必要なら delete 併用を検討します(compact,delete)。

compaction時の墓石(null値)は delete.retention.ms を過ぎるまで保持されます。これが短すぎると遅延したコンシューマが削除イベントを見逃す可能性があります。compact と delete を併用する場合、時間保持で早期削除されないよう、retention.ms とセグメントロールの兼ね合いに注意します。

  • compactionはキー必須。値がnullは墓石として削除マーク
  • min.cleanable.dirty.ratio と cleaner スレッドで圧縮タイミングを制御
  • compact,delete 併用時は 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%)を必ず含めます。セグメントはアクティブ中は削除不可で一時的に上ぶれるため、監視と容量アラートのしきい値も含めて設計します。

  • 平均実効スループット = 入力B/s × 圧縮後係数(例: 0.5)
  • 必要ディスク ≒ 平均実効スループット × 保持秒 × レプリケーション係数 × (1+ヘッドルーム)
  • サイズ保持なら retention.bytes × パーティション数 × レプリケーション係数 が上限

概算の手計算スクリプト(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 のスループットと遅延を継続観測します。

  • 閾値: ディスク70%で警告、80%で対応、90%で緊急(例)
  • 強制ロール: 一時的に log.roll.ms を短くして削除を促進(サーバー再起動が必要)
  • 再処理SLAが厳しい場合、サイズ保持単独は避け最低保証期間を別途担保
  • クラウドのティアードストレージ採用時は、ローカル保持とリモート保持の課金モデルを個別に確認

運用時に役立つクイック確認コマンド

# ブローカのログディレクトリ使用量(例)
$ 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=UnderReplicatedPartitions

問題で確認

CCAAK

問題 1

高スパイクが時折発生するイベントトピックでコスト上限を厳守したい。一方で最低48時間の再処理猶予は必要。最も適切な保持設計はどれか。

  1. A. retention.bytes を十分大きく取り、ヘッドルーム込みで48時間相当のデータを収まるよう見積もる。時間保持は設定しない。
  2. B. retention.ms=172800000 のみを設定し、サイズ保持は無効化する。
  3. C. retention.bytes を厳密な上限に設定し、スパイク対策として log.retention.check.interval.ms を短くする。
  4. D. cleanup.policy=compact のみにしてサイズ・時間保持は無効化する。

正解: A

スパイクにより時間保持のみではディスクが溢れる恐れがあるため、サイズ上限でコストを固定するのが前提。ただし最低48時間の再処理猶予を満たすには、平常時だけでなくスパイク時の一時的な上振れも含めて retention.bytes を見積もる必要がある。Cはチェック間隔を短くしても上限を厳しくすると48時間保証が崩れる可能性が高い。Bはコスト上限を制御できない。Dは履歴保持要件を満たさない。

よくある質問

時間とサイズを同時に設定したらどうなる?

どちらの条件でも削除が発火します。総サイズが上限を超えれば最古から削除、時間が経過していれば古いセグメントが削除されます。いずれもアクティブセグメントは対象外です。

削除が進まないのはなぜ?

アクティブセグメントのままでロールされていない、log.retention.check.interval.ms が長い、セグメントの最終更新時刻が保持閾値を超えていない、あるいはブローカのクリーンアップ処理が遅延している可能性があります。log.roll.ms の設定や監視で状況を確認してください。

compactionと時間保持を併用すると何に注意?

墓石(null値)を delete.retention.ms の間は保持する必要があります。これが短いと遅延したコンシューマが削除を取りこぼします。retention.ms により早期にセグメントごと消えて墓石が流れ切らないケースもあるため、セグメントロールと各タイマーの整合を取ってください。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Kafka

Kafka Topic と Partition の基礎: 分散とスケーラビリティの要

CCDAK 対策と実務の両立を意識し、Topic/Partition/Replica/Consumer Group の役...

Kafka

CCDAK 試験ガイド:出題範囲・配点・申込み・対策

Confluent Certified Developer for Apache Kafka (CCDAK) の出題範囲...

Kafka

Confluent Certified Administrator (CCAAK) 対策: 出題範囲・配点の考え方・運用観点の要点

CCAAKに向けて、試験領域の押さえどころを運用目線で整理。プロダクションで通用する設定・監視・セキュリティの実践知を、...

Kafka

Kafka の Replica と In-Sync Replicas を正しく設計する: 耐障害性と一貫性

レプリカとISRの仕組みを起点に、acks と min.insync.replicas、クリーン/アンクリーンリーダー選...

Kafka

Kafka の Offset とコミット: ポジション管理と at-least-once の基礎

CCDAK 対策と実務の両立を意識して、Kafka コンシューマのオフセット管理とコミット戦略を整理。at-least-...

Kafkaの記事一覧 (101件)
© 2026 NicheeLab All rights reserved.