Event Sourcingは、エンティティの“現在の状態”を直接保存するのではなく、“状態を生み出したイベント列”を唯一のソース・オブ・トゥルースとして扱う設計です。Kafkaはイベントの追記・配布・再生に強く、パーティション単位の順序性や保持戦略、トランザクションなど、Event Sourcingに必要な機能を備えています。
本稿はConfluent Certified Developer for Apache Kafka (CCDAK)の出題領域に沿って、設計ポイントを実務的に解説します。公式ドキュメントの挙動を前提に、安定した概念・機能のみを扱います。
Event Sourcingでは、イベントが唯一の真実であり、状態は派生物として再構築可能であることが前提です。Kafkaはトピックへの追記型ログ、パーティション内の順序保証、保持・圧縮のポリシーにより、長期保存と再生を両立できます。
CCDAKで問われやすいのは、保持(delete)とログ圧縮(compact)の違い、パーティション内順序とキー設計、トランザクショナル・プロデューサやidempotenceの意味、コンスーマのisolation.levelなどです。
| 観点 | Event Sourcing + Kafka | CRUD中心(状態保存) | CDC(ログベース変更取得) |
|---|---|---|---|
| ソース・オブ・トゥルース | イベントログ(追記) | 現在状態(上書き) | DBが主、変更を後追い |
| 再生可能性 | 全履歴から再構築が前提 | 難しい/別途監査が必要 | ある程度可能(保持期間依存) |
| 順序保証 | キー内で厳密(パーティション内) | アプリ/DBに依存 | DBコミット順≠ビジネス順の可能性 |
| スキーマ進化 | Schema Registryで互換性管理 | DBスキーマ移行が中心 | CDCツールの互換性制約あり |
| 監査・トレース | イベントが監査ログを兼ねる | 追加設計が必要 | 変更履歴として活用可能 |
順序は“パーティション内のみ”で保証されます。従って、ビジネス上の集約(例: accountId, orderId)をキーに選ぶのが基本です。パーティション数はスループットと並列度に影響し、キーのカーディナリティと均一性を見ます。
保持(delete)は時間/サイズでログを削除します。圧縮(compact)は同一キーの最新レコードだけを保持し、過去の重複キーは削除します。両方を併用(“compact,delete”)すれば、最新像を保ちつつ、極端に古いセグメントを掃除できます。
Kafkaのidempotent producerはネットワーク再送時でも重複を書き込まないようにします。さらにtransactional.idを設定すると、複数のトピック/パーティションへの一括書き込みと、read_committedコンスーマによるコミット済みのみの読み取りが可能になり、Kafka内の処理でexactly-once semanticsに到達できます。
ただし外部DBなどKafka外部まで含めた“厳密なEOS”は保証範囲外です。外部システム連携はOutboxや二段階構成で“少なくとも一度+冪等処理”に寄せるのが実務的です。
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では“イベント種別ごとに明確なスキーマ”を保ち、アプリ側でアップキャスター(古いイベントを新形式に持ち上げる)を用意しておくと安全です。
イベントをKStreamとして取り込み、キー集約してKTableにマテリアライズすると、“最新状態”のローカル/リモートストアが得られます。compactなトピックはKTableに向いており、deleteトゥームストーンで削除も表現可能です。
再生が必要なときは、コンシューマのオフセットを最初に戻す(例: auto.offset.reset=earliest もしくは手動seek)か、新しいコンシューマグループで読み直します。スナップショット用に“状態スナップショット・トピック”を定期出力し、履歴再生時間を短縮する設計も有効です。
Event Sourcingのデータフロー(概念図)
運用では、レイテンシとラグ、保持サイズ、圧縮の進行、トゥームストーン滞留、スキーマ互換違反、再平衡の影響を監視します。Event Sourcingでは“消せない”前提があるため、コスト見積もりとアーカイブ/スナップショット戦略が重要です。
試験対策としては、保持vs圧縮、キーと順序、idempotent/transactional設定、read_committed、KTableとKStreamの違い、スキーマ互換性レベル、ACL/セキュリティの基本が頻出です。
CCDAK
問題 1
ユーザーアカウントの残高をEvent Sourcingで管理する。外部DBを使わずKafka上で最新状態を保持しつつ、必要に応じて全履歴から再構築できるようにしたい。最も適切な設計はどれか。
正解: 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の順序保証はパーティション内のみです。異なるキー間や複数集約をまたぐ順序は保証されないため、因果関係を表すイベント設計や、ワークフロー用の別トピック・オーケストレーションで扱います。
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-...