Kafka

Kafkaのウィンドウ処理:Tumbling / Hopping / Sessionを正しく使い分ける

2026-04-19
NicheeLab編集部

ウィンドウ処理は「いつのデータをどこまでまとめるか」を決める時間軸の設計。Kafkaでは基本的にイベント時刻ベースで考えます。

Tumbling(固定長・非重複)、Hopping(固定長・重複)、Session(可変長・マージ)を区別して選ぶのが第一歩。

ウィンドウ処理の基本とタイムセマンティクス

Kafkaのウィンドウ処理は、連続するストリームを時間で区切って集計・結合するための仕組みです。Kafka Streams DSLとksqlDBはいずれも原則としてイベント時刻(レコードのタイムスタンプ)を用います。ストリーム時間は、観測したイベント時刻の最大値で進みます。

遅延イベント(到着順が前後するデータ)を扱うには、ウィンドウ終端後にどの程度まで受け入れるか(Grace)を設定します。ウィンドウは「ストリーム時間が ウィンドウ終端+Grace に達した時点」で閉じられ、それ以降に属するレコードは遅着として破棄されます。

正しく時刻を扱うには、TimestampExtractor(Kafka Streams)やTIMESTAMP列(ksqlDB)を適切に指定し、期待するイベント時刻を付与することが重要です。

  • イベント時刻が基本。処理時刻ベースの近似は試験でも実務でも推奨されません。
  • ストリーム時間は最大観測時刻で進む。よって高い時刻のレコードが1件でも到来すると、過去ウィンドウの閉鎖が進む可能性があります。
  • 遅延受け入れはGraceで明示。Graceが短すぎると正確性を失い、長すぎるとレイテンシとメモリ消費が増えます。

Tumbling / Hopping / Session の違い(比較表)

3種のウィンドウは境界の作り方と重なり方が決定的に異なります。要件(重複カウント可否、ユーザー行動のかたまり検出、レポートの粒度)に合わせて選択します。特に試験(CCDAK)では、定義と使いどころを問う設問が繰り返し出題されます。

Sessionは非活動ギャップで区切る可変長。遅延イベントを契機に別々のセッションがマージされることがある、という点が実務・試験ともに重要です。

  • Tumbling: 固定長・非重複。分単位のKPIやウィンドウごとに唯一の結果が欲しいケースに最適。
  • Hopping: 固定長・重複。スライディング分析(移動平均、移動カウント)に向く。重複計上を理解して使う。
  • Session: 可変長・マージあり。ユーザー行動の「まとまり」を捉える用途に強い。
種別境界/長さオーバーラップGrace(遅延許容)
Tumbling固定長。例: 1分ごと [00:00,00:01)なし(非重複)ウィンドウ終端後、Graceまで受け入れ
Hopping固定長+スライド。例: 長さ5分・1分スライドあり(同一イベントが複数ウィンドウに入る)終端後、Graceまで受け入れ(各ウィンドウごと)
Session可変長。非活動ギャップで区切り、活動で延長マージあり(遅延でセッション結合し得る)セッション終端後、Graceまで受け入れ

遅延イベントとGrace、ストリーム時間の挙動(図解)

ウィンドウは、ストリーム時間がウィンドウ終端+Graceに到達するまで「開いたまま」です。ストリーム時間は観測したイベント時刻の最大値で進むため、将来時刻のレコードが到着すると過去ウィンドウが一気に閉じることがあります。

以下の図は、Tumblingウィンドウ [0,5), [5,10) と、Grace=2 の例です。ts=4 の遅延イベントがストリーム時間6の時点で到着しても、5+2=7 まではウィンドウ[0,5)が開いているため取り込まれます。

  • ウィンドウ閉鎖条件: stream-time >= window-end + grace
  • 遅延の受け入れは「閉鎖前まで」。閉鎖後に到着したレコードは破棄される(メトリクスで観測可能)。
  • 高い時刻のレコードはstream-timeを押し上げる。設計時はデータ分布を把握する。

ウィンドウ終端とGraceのイメージ(Tumbling, Grace=2)

time --->
0    2    4    6    8   10
|----|----|----|----|----|
[ W1:0-5 )                [ W2:5-10 )
|-------------------------|-------------------------

イベント到着:
 e1: ts=3, arrive@3   -> 属する: W1(オンタイム)
 e2: ts=6, arrive@6   -> 属する: W2(オンタイム)=> stream-time = 6
 e3: ts=4, arrive@6   -> 遅延だが W1 に取り込み可能(stream-time 6 < 5+Grace 7)
 e4: ts=1, arrive@9   -> W1は既に閉鎖(stream-time>=7)=> 遅着として破棄

実装パターン(Kafka Streams DSL と ksqlDB)

Kafka Streams DSLでは、TimeWindows.ofSizeAndGrace と SessionWindows.ofInactivityGapAndGrace を用いてウィンドウ長とGraceを明示します。HoppingはadvanceByでスライド幅を指定します。Sessionではマージ関数(Aggregator Merger)が必須です。

ksqlDBでは、WINDOW句でTUMBLING/HOPPING/SESSIONを指定し、SIZE/ADVANCE BY/GRACE PERIODを合わせて宣言します。最終結果のみを取りたい場合はEMIT FINALを併用します(中間更新を抑制)。実際のバージョンにより句の細かな位置やサポートは変わることがあるため、運用前に該当バージョンのドキュメントを確認してください。

  • Kafka Streams: ofSizeAndGrace / ofInactivityGapAndGrace を使う。保持はウィンドウ長+Grace以上に。
  • HoppingはadvanceByでスライド設定。重複集計を前提にダウンストリームで扱う。
  • ksqlDB: WINDOW句とGRACE PERIOD、必要に応じてEMIT FINAL。

Kafka Streams DSL と ksqlDB のサンプル

// Kafka Streams (Java)
KStream<String, String> source = builder.stream("input");

// 1) Tumbling 1分 + Grace 5分(イベント時刻ベース)
KTable<Windowed<String>, Long> tumbling = source
    .groupByKey()
    .windowedBy(TimeWindows.ofSizeAndGrace(Duration.ofMinutes(1), Duration.ofMinutes(5)))
    .count();

// 必要ならウィンドウ閉鎖後のみ出力(中間を抑制)
KTable<Windowed<String>, Long> tumblingFinal = tumbling
    .suppress(Suppressed.untilWindowCloses(Suppressed.BufferConfig.unbounded()));

// 2) Hopping(長さ5分・1分スライド)+ Grace 5分
KTable<Windowed<String>, Long> hopping = source
    .groupByKey()
    .windowedBy(
        TimeWindows.ofSizeAndGrace(Duration.ofMinutes(5), Duration.ofMinutes(5))
                   .advanceBy(Duration.ofMinutes(1))
    )
    .count();

// 3) Session(非活動ギャップ5分・Grace 10分)
KTable<Windowed<String>, Long> sessions = source
    .groupByKey()
    .windowedBy(SessionWindows.ofInactivityGapAndGrace(Duration.ofMinutes(5), Duration.ofMinutes(10)))
    .aggregate(
        () -> 0L,
        (key, value, agg) -> agg + 1,
        (agg1, agg2) -> agg1 + agg2, // セッションマージ時の結合関数
        Materialized.with(Serdes.String(), Serdes.Long())
    );

// ksqlDB
-- ストリーム定義(イベント時刻としてtsを使用)
CREATE STREAM clicks (user_id VARCHAR, ts BIGINT)
  WITH (KAFKA_TOPIC='clicks', VALUE_FORMAT='JSON', TIMESTAMP='ts');

-- Tumbling 1分 + Grace 5分、最終結果のみ
CREATE TABLE clicks_tumbling AS
  SELECT user_id, COUNT(*) AS c
  FROM clicks
  WINDOW TUMBLING (SIZE 1 MINUTE, GRACE PERIOD 5 MINUTES)
  GROUP BY user_id
  EMIT FINAL;

-- Hopping(長さ5分・1分スライド)+ Grace 5分
CREATE TABLE clicks_hopping AS
  SELECT user_id, COUNT(*) AS c
  FROM clicks
  WINDOW HOPPING (SIZE 5 MINUTES, ADVANCE BY 1 MINUTE, GRACE PERIOD 5 MINUTES)
  GROUP BY user_id
  EMIT FINAL;

-- Session(ギャップ60秒・Grace 5分)
CREATE TABLE clicks_session AS
  SELECT user_id, COUNT(*) AS c
  FROM clicks
  WINDOW SESSION (60 SECONDS, GRACE PERIOD 5 MINUTES)
  GROUP BY user_id
  EMIT FINAL;

-- 注: 実運用ではバージョンによりWINDOW/GRACE句の詳細が異なる場合があります。

状態ストアの保持と抑制(Suppression)・出力戦略

ウィンドウ集計は内部に状態(ウィンドウストア)を保持します。保持期間は少なくとも「ウィンドウ長+Grace」以上が必要です。Kafka StreamsのofSizeAndGraceやofInactivityGapAndGraceを使う場合、この前提を満たす設定を行うのが実務上の定石です。

抑制(Suppression)はウィンドウ閉鎖まで中間結果を溜め、閉鎖時に最終結果のみを下流へ流します。untilWindowClosesは分かりやすい一方、バッファが増えメモリプレッシャーになるため、負荷・レイテンシ要件と合わせて評価します。ksqlDBではEMIT FINALが近い役割を担います。

  • 保持は「長さ+Grace」が原則。足りないと遅延イベントを受け入れられない。
  • Suppression/EMIT FINALはレイテンシとメモリのトレードオフ。KPI最終値のみが必要な場合に有効。
  • 高カーディナリティのキーではストアサイズが急増するため、キー設計と圧縮トピック運用を併せて検討する。

CCDAK試験対策の要点と落とし穴

出題の定番は、ウィンドウ種別の定義、イベント時刻と処理時刻の違い、Graceによる遅延許容、セッションマージの挙動です。特にSessionのマージ条件(非活動ギャップをまたぐ遅延により別セッションが結合する)と、ウィンドウの閉鎖条件(stream-time >= window-end + grace)は暗記レベルで押さえましょう。

Hoppingは重複カウントが前提である点、Suppression/EMIT FINALの使いどころ、保持期間が足りないと遅延を取り込めない点は実務でも誤解が多く、試験でもひっかけに使われます。

  • TimestampExtractor/TIMESTAMP指定を忘れない。処理時刻で近似しない。
  • Sessionはマージ時に再集計される。マージ関数が必要。
  • ウィンドウ閉鎖はstream-time基準。レコード到着時刻ではない。

問題で確認

CCDAK

問題 1

Kafka Streamsでイベント時刻に基づく1分Tumbling集計を行い、ウィンドウ終端後5分まで遅延イベントを受け入れたい。最も適切な設定はどれか?

  1. TimeWindows.ofSizeAndGrace(Duration.ofMinutes(1), Duration.ofMinutes(5)) を使ってwindowedByに指定する
  2. TimeWindows.of(Duration.ofMinutes(1)).advanceBy(Duration.ofMinutes(1)) を使う
  3. Suppressed.untilWindowClosesのみを設定すれば遅延を5分受け入れられる
  4. Graceを0にしてMaterialized#withRetentionだけを長く設定する

正解: A

遅延受け入れはGraceで制御する。ofSizeAndGrace(1分, 5分)が正解。advanceByはHoppingのスライド設定であり、遅延許容は設定しない。Suppressionは出力タイミングであり遅延の受け入れとは別。保持期間は十分に必要だが、Graceを0のままでは遅延を受け入れない。

よくある質問

Graceを超えて到着した遅着イベントはどうなる?捕捉する方法はある?

ウィンドウが閉鎖(stream-time >= window-end + grace)した後に到着したレコードは破棄されます(Kafka Streamsではメトリクスにカウントされる)。捕捉したい場合は、ウィンドウ前に独自の遅延判定(現在のstream-timeとレコード時刻の差など)で分岐し、別トピックに退避する等の処理を実装します。ksqlDBには標準の“遅着専用出力”はありません。

Sessionウィンドウのマージはいつ起きる?何が再計算される?

同一キーで、非活動ギャップをまたいでいた2つのセッションが、遅延イベントの到着などでつながるとマージが発生します。マージ時は開始・終了時刻が更新され、集計値はマージ関数(aggregator merger)で再計算されます。

イベント時刻と処理時刻のどちらを使うべき?

Kafka Streams/ksqlDBの設計意図はイベント時刻優先です。TimestampExtractorやTIMESTAMP列を適切に設定し、データに内在する時刻でウィンドウ化してください。処理時刻はレイテンシ評価や暫定可視化には使えますが、正確な集計には向きません。

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

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.