Kafka

Kafkaで実践するEvent Sourcingパターン:状態ではなくイベントで管理する設計

2026-04-19
NicheeLab編集部

Event Sourcingは、エンティティの“現在の状態”を直接保存するのではなく、“状態を生み出したイベント列”を唯一のソース・オブ・トゥルースとして扱う設計です。Kafkaはイベントの追記・配布・再生に強く、パーティション単位の順序性や保持戦略、トランザクションなど、Event Sourcingに必要な機能を備えています。

本稿はConfluent Certified Developer for Apache Kafka (CCDAK)の出題領域に沿って、設計ポイントを実務的に解説します。公式ドキュメントの挙動を前提に、安定した概念・機能のみを扱います。

Event Sourcingの要点とKafkaでの適用

Event Sourcingでは、イベントが唯一の真実であり、状態は派生物として再構築可能であることが前提です。Kafkaはトピックへの追記型ログ、パーティション内の順序保証、保持・圧縮のポリシーにより、長期保存と再生を両立できます。

CCDAKで問われやすいのは、保持(delete)とログ圧縮(compact)の違い、パーティション内順序とキー設計、トランザクショナル・プロデューサやidempotenceの意味、コンスーマのisolation.levelなどです。

  • イベントを不変データとして記録し、状態は後から再生して得る
  • キーでパーティションにルーティングし、キー内順序を保証
  • 保持(delete)と圧縮(compact)を使い分けて“履歴”と“最新像”を両立
  • 外部DBとの整合はOutboxなどのパターンで境界を明確化
観点Event Sourcing + KafkaCRUD中心(状態保存)CDC(ログベース変更取得)
ソース・オブ・トゥルースイベントログ(追記)現在状態(上書き)DBが主、変更を後追い
再生可能性全履歴から再構築が前提難しい/別途監査が必要ある程度可能(保持期間依存)
順序保証キー内で厳密(パーティション内)アプリ/DBに依存DBコミット順≠ビジネス順の可能性
スキーマ進化Schema Registryで互換性管理DBスキーマ移行が中心CDCツールの互換性制約あり
監査・トレースイベントが監査ログを兼ねる追加設計が必要変更履歴として活用可能

トピック・キー・保持設計:順序と寿命を決める

順序は“パーティション内のみ”で保証されます。従って、ビジネス上の集約(例: accountId, orderId)をキーに選ぶのが基本です。パーティション数はスループットと並列度に影響し、キーのカーディナリティと均一性を見ます。

保持(delete)は時間/サイズでログを削除します。圧縮(compact)は同一キーの最新レコードだけを保持し、過去の重複キーは削除します。両方を併用(“compact,delete”)すれば、最新像を保ちつつ、極端に古いセグメントを掃除できます。

  • キーは“順序保証を必要とする単位”で選ぶ
  • cleanup.policy=compactで“最新像KTable”を支える
  • retention.ms/bytesで履歴の寿命・コストを制御
  • パーティション増減は再分散と順序影響に注意(キー→パーティションが変わり得る)

重複と一貫性:Idempotent/Transactional ProducerとEOS

Kafkaのidempotent producerはネットワーク再送時でも重複を書き込まないようにします。さらにtransactional.idを設定すると、複数のトピック/パーティションへの一括書き込みと、read_committedコンスーマによるコミット済みのみの読み取りが可能になり、Kafka内の処理でexactly-once semanticsに到達できます。

ただし外部DBなどKafka外部まで含めた“厳密なEOS”は保証範囲外です。外部システム連携はOutboxや二段階構成で“少なくとも一度+冪等処理”に寄せるのが実務的です。

  • enable.idempotence=true と acks=all はセットで理解
  • transactional.id の一意性とfencingで“二重コミット”を防止
  • コンスーマは isolation.level=read_committed で未コミットを除外
  • Kafka StreamsのEOSは内部的に上記を活用(バージョン差異の詳細は公式に準拠)

Transactional Producerの最小構成(Java)

Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "broker:9092");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, org.apache.kafka.common.serialization.StringSerializer.class.getName());
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, org.apache.kafka.common.serialization.ByteArraySerializer.class.getName());
props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, "true");
props.put(ProducerConfig.ACKS_CONFIG, "all");
props.put(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION, "5"); // 再順序化を避ける上限
props.put(ProducerConfig.RETRIES_CONFIG, Integer.toString(Integer.MAX_VALUE));
props.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG, "orders-tx-1");

KafkaProducer<String, byte[]> producer = new KafkaProducer<>(props);
producer.initTransactions();

try {
  producer.beginTransaction();
  // バッチでイベントを書き込む
  for (Event e : events) {
    ProducerRecord<String, byte[]> rec = new ProducerRecord<>("orders-events", e.key(), e.payload());
    producer.send(rec);
  }
  producer.commitTransaction();
} catch (org.apache.kafka.common.errors.ProducerFencedException fenced) {
  // 同一 transactional.id の別インスタンス起動などでフェンスされた
  producer.close();
  throw fenced;
} catch (Exception ex) {
  producer.abortTransaction();
}

スキーマ管理と進化:互換性を壊さないイベント

イベントは長期に渡り再生されるため、スキーマ進化は後方互換(backward)や前方互換(forward)を意識して管理します。Confluent Schema Registryを用い、互換性レベルを適切に設定します。フィールドの追加は後方互換になりやすく、必須フィールドの削除・型変更は互換性を壊しがちです。

サブジェクト命名戦略(例: TopicNameStrategy, RecordNameStrategy)により、スキーマの粒度と共有度合いが変わります。Event Sourcingでは“イベント種別ごとに明確なスキーマ”を保ち、アプリ側でアップキャスター(古いイベントを新形式に持ち上げる)を用意しておくと安全です。

  • 後方互換を基本に、古いイベントの再生を常に可能にする
  • 必須→任意への緩和、デフォルト値の付与で進化を吸収
  • サブジェクト命名戦略は再利用性と衝突回避のトレードオフ
  • スキーマ破壊が避けられない場合は新しいイベントタイプで表現

再生とマテリアライズ:KTable/State Storeで“現在”を得る

イベントをKStreamとして取り込み、キー集約してKTableにマテリアライズすると、“最新状態”のローカル/リモートストアが得られます。compactなトピックはKTableに向いており、deleteトゥームストーンで削除も表現可能です。

再生が必要なときは、コンシューマのオフセットを最初に戻す(例: auto.offset.reset=earliest もしくは手動seek)か、新しいコンシューマグループで読み直します。スナップショット用に“状態スナップショット・トピック”を定期出力し、履歴再生時間を短縮する設計も有効です。

  • KStream→aggregate→KTableで現在値を構築
  • compactトピックは“キー単位の最新像”に最適
  • スナップショット+イベント差分で高速復元
  • オフセット管理は“いつの状態を見たいか”の明示

Event Sourcingのデータフロー(概念図)

ProducersOrderCreated,...Kafka Topicappend-only logStreams/KTableMaterializationState StoreRocksDB etc.Query/ServingProducers → Kafka Topic → Streams/KTable → State Store → Query/Serving

運用の勘所とCCDAK直結ポイント

運用では、レイテンシとラグ、保持サイズ、圧縮の進行、トゥームストーン滞留、スキーマ互換違反、再平衡の影響を監視します。Event Sourcingでは“消せない”前提があるため、コスト見積もりとアーカイブ/スナップショット戦略が重要です。

試験対策としては、保持vs圧縮、キーと順序、idempotent/transactional設定、read_committed、KTableとKStreamの違い、スキーマ互換性レベル、ACL/セキュリティの基本が頻出です。

  • 監視: コンシューマラグ、ログサイズ、compaction lag、エラーレート
  • DLT(死信トピック)で壊れたイベントを隔離し再処理
  • ACLとトランザクションIDの適切な権限付与
  • 再処理戦略: 新グループで全再生、スナップショット起点で差分適用

問題で確認

CCDAK

問題 1

ユーザーアカウントの残高をEvent Sourcingで管理する。外部DBを使わずKafka上で最新状態を保持しつつ、必要に応じて全履歴から再構築できるようにしたい。最も適切な設計はどれか。

  1. アカウントIDをキーにしてイベントを1つのトピックに追記し、cleanup.policy=compactを有効化。KTableにマテリアライズして最新残高を提供する。
  2. 保持はdelete専用でretention.msを短くし、最新状態は別の状態トピックに上書き保存する。
  3. パーティション数を1に固定し、キーは未設定(null)にして全順序を保証する。
  4. スキーマ進化は考慮せず、イベントの値を自由形式のJSON文字列で保存する。

正解: A

最新像をKafka内で保ち、履歴の再生も可能にするには、キー単位での順序を維持しつつcompactを用いてKTable化するのが定石。Bは履歴が短く再生困難、Cはスケールしない上にキー順序を活かせない、Dは長期運用で破壊的変更を招きやすく試験的にも非推奨。

よくある質問

Event SourcingとCDCの違いは?どちらをいつ使うべき?

Event Sourcingはイベントが唯一の真実で、状態は再生で得ます。設計の中心にイベントがあり、書き込み経路自体がイベント駆動です。CDCは既存DBの変更を後追いで取り出す方式で、レガシー統合や段階移行に向きます。新規設計で履歴・監査・再生を重視するならEvent Sourcing、既存DBからストリーム化したいならCDCが適しています。

全履歴の再処理が必要だが、retention超過で一部が削除されていた場合の対処は?

compactトピックの“最新像”と、定期的なスナップショットを組み合わせておくのが安全策です。既に消えている場合は、アーカイブ(ミラー/外部ストレージ)から復元するか、スナップショットから差分だけ再生します。将来的にはretentionとストレージ計画を見直し、compactとスナップショットを併用してください。

1つの集約の順序保証はどう担保する?クロス集約の順序は?

集約キー(例: orderId)をメッセージキーに設定し、同一キーが同一パーティションに行くようにします。Kafkaの順序保証はパーティション内のみです。異なるキー間や複数集約をまたぐ順序は保証されないため、因果関係を表すイベント設計や、ワークフロー用の別トピック・オーケストレーションで扱います。

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

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.