Mímisbrunnr知恵の泉

← データエンジニアリング 一覧

🎓 レベル:発展 | 重要度:A(必須)

📎 前提:メッセージキューとイベントストリーミングバッチ処理とストリーム処理 | 関連:ウィンドウ関数

要点(BLUF)

概念 ── 無限の流れを区切る

バッチは「有限のデータの塊」を処理しますが、ストリームは「終わらない流れ」。そのままでは集計できないので、ウィンドウで時間を区切って「この10秒分の合計」を出します。

flowchart LR
    E["イベント列(無限)"] --> W0["window 0-10秒"]
    E --> W1["window 10-20秒"]
    E --> W2["window 20-30秒"]
    W0 --> A0["集計"]
    W1 --> A1["集計"]
    W2 --> A2["集計"]

仕組み ── イベント時間ウィンドウと遅延データ

10秒幅のタンブリングウィンドウで集計し、watermarkを超えて遅れて届いたデータは隔離します。

WIN = 10
def window_start(t): return (t // WIN) * WIN
# watermark(処理済みの最大イベント時間)より十分古いものは遅延として隔離
if t < watermark - WIN:
    late.append((t, v))
else:
    windows[window_start(t)] ...  # 該当ウィンドウに加算

実行結果(実機・純Pythonで再現):

ウィンドウ別集計(イベント時間基準):
  [ 0,10): 件数=3 合計=60
  [10,20): 件数=3 合計=150
  [20,30): 件数=1 合計=70
遅延データ(watermark超過で隔離): [(5, 99)]

イベント時間で各ウィンドウに正しく振り分けられ、最後に届いた (5, 99)(本来は[0,10)のはずが、watermarkが22まで進んだ後に到着)は遅延データとして隔離されました。「いつまで待って集計を確定するか」を決めるのがwatermarkの役割です。

設計の勘所 ── ウィンドウと時間の扱い

種類用途
タンブリング重ならない固定幅1分ごとの売上
スライディング重なる固定幅直近5分の移動平均
セッション活動の切れ目で区切るユーザーの操作セッション

なぜそうするか ── 鮮度のための難しさを引き受ける

なぜこの複雑さを引き受けるのか。**秒単位の鮮度がビジネス価値を持つ場面(不正検知・即時モニタリング)**があるからです。バッチでは「1時間後に異常が分かる」では遅い。ただし バッチ処理とストリーム処理 の通り、鮮度が要らないならバッチが断然簡単。ストリームは「時間・順序・遅延・状態」という固有の難しさを抱えるので、鮮度要件が明確なときだけ選びます。なお、ウィンドウ集計の発想自体は ウィンドウ関数 の枠付き集計と同じ——「区切って、その中で集める」が両者の共通形です。

⚠️ よくある落とし穴

対応ラボ

data-engineering-study/labs/07_streaming_orchestration.pyPYTHONIOENCODING=utf-8 で実行・ウィンドウ集計と遅延データ隔離を確認済み)。

関連

第7章 ストリーミングとオーケストレーション 目次