ひとことで言うと#
ストリーム処理パターンは、データが到着した瞬間に逐次処理する設計手法で、バッチ処理の「溜めてから処理」ではなくリアルタイムに近い応答を実現するアーキテクチャ群を指します。
用語の定義#
押さえておきたい用語
- イベントストリーム(Event Stream):時刻順に連続的に発生するデータの流れ。メッセージキュー上のレコード列として実装されることが多い
- ウィンドウ処理(Windowing):無限に流れるストリームを時間や件数で区切り、集計可能な有限の塊にする手法。タンブリング・スライディング・セッションの3種が代表的
- ウォーターマーク(Watermark):イベントの遅延を考慮して「ここまでのデータは揃った」と判断する基準時刻。遅延データの取り扱いを制御する仕組み
- Exactly-once セマンティクス:メッセージが重複も欠損もなく正確に1回だけ処理されることを保証する配信特性
- バックプレッシャー(Backpressure):下流の処理が追いつかないとき、上流にデータ送信速度を抑えるよう伝える制御メカニズム
全体像#
イベント発生
ソースからデータ到着
→ソースからデータ到着
メッセージキュー
Kafka等でバッファリング
→Kafka等でバッファリング
ストリーム処理
フィルタ・集約・結合
→フィルタ・集約・結合
リアルタイム出力
アラート・ダッシュボード
アラート・ダッシュボード
こんな悩みに効く#
- 不正検知のアラートが夜間バッチの翌朝にしか届かず、被害が拡大してから対応することになる
- ユーザーの行動ログをリアルタイムに集計してパーソナライズしたいが、バッチ処理では更新が遅すぎる
- IoTセンサーのデータが毎秒数万件届くが、全件をDBに書き込むと処理が追いつかない
基本の使い方#
バッチとストリームの境界を決める
すべてをストリーム化する必要はありません。「検知から対応まで何分以内が許容か」を基準に、リアルタイム性が必要な処理だけをストリームに切り出します。レポーティングや過去データの再集計はバッチに残すのが合理的です。
メッセージキューを選定・設計する
Kafka、Kinesis、Pub/Subなどからスループットと運用負荷で選定します。トピックの分割粒度は「処理単位ごとに1トピック」を基本とし、パーティション数はピーク時の秒間メッセージ数から逆算して設定します。
ウィンドウ処理とウォーターマークを設計する
集計の目的に合ったウィンドウ型(タンブリング/スライディング/セッション)を選び、遅延データの許容時間をウォーターマークで設定します。遅延許容を長くすると正確性は上がりますが、結果の出力も遅くなるトレードオフがあります。
障害時のリカバリ戦略を設計する
チェックポイントの間隔とステートバックエンドの種類を決めます。Exactly-onceが必要な場面(決済、在庫)と、at-least-onceで十分な場面(ログ集計)を区別し、過剰な保証でスループットを犠牲にしないよう設計します。
具体例#
決済サービスの不正検知
月間処理件数800万件のオンライン決済サービスが、Kafkaを経由してFlink上でリアルタイム不正検知を構築。5分間のタンブリングウィンドウでユーザーごとの決済頻度と金額パターンを集計し、過去30日の行動プロファイルと比較する。ルールベース(同一カードで5分間に3件以上)とMLスコアリングを組み合わせた結果、不正検知の平均所要時間がバッチ処理の12時間から1.8秒に短縮。不正取引による損失額が月あたり約2,400万円から600万円に減少した。
動画配信のリアルタイムレコメンド
月間利用者500万人の動画配信サービスが、視聴イベントをKinesis Data Streamsで収集し、30秒間のスライディングウィンドウで「今見ている」コンテンツのジャンル分布をリアルタイム計算。セッションウィンドウ(無操作15分で切れ目)でユーザーの視聴セッションを区切り、セッション内の視聴傾向から次の推薦を動的に変更する仕組みを導入。レコメンドのクリック率が従来のバッチ更新(日次)比で1.8倍、1セッションあたりの平均視聴時間が23分から31分に伸びた。
製造ラインの品質監視
自動車部品メーカーが、溶接ロボット120台のセンサーデータ(温度・電流・振動を毎秒10回計測)をPub/Sub経由でDataflow上にストリーム処理基盤を構築。3秒間のタンブリングウィンドウで各溶接ポイントの温度偏差を計算し、閾値を超えた場合は200ミリ秒以内にライン停止信号を送出する。導入前は後工程のX線検査で発見していた溶接不良(発見まで平均4.5時間)を、リアルタイム検知で即時対応に切り替えた結果、不良品流出率が0.8%から0.12%に改善し、手戻りコストが年間約1.2億円削減された。
やりがちな失敗パターン#
| 失敗 | 原因 | 対策 |
|---|---|---|
| 処理の遅延がどんどん拡大する | バックプレッシャー制御を入れずに上流がデータを送り続ける | Consumer側のスループットを監視し、閾値を超えたらソース側のレートを制限する仕組みを入れる |
| データの重複や欠損が発生する | at-least-once配信なのに冪等性を担保していない | 冪等キー(イベントID + タイムスタンプ)で重複を除去するか、Exactly-onceが必要な箇所を特定して設計する |
| ウィンドウ集計の数値がバッチと合わない | 遅延データの扱い(ウォーターマーク設定)がバッチと異なる | ウォーターマークの遅延許容時間を十分に取るか、遅延分の補正バッチを別途回す |
| 障害復旧に数時間かかる | チェックポイント間隔が長すぎ、大量の再処理が走る | チェックポイントを1〜5分間隔に設定し、ステートのサイズもインクリメンタルに管理する |
まとめ#
ストリーム処理を導入する際の最大の判断ポイントは「本当にリアルタイムが必要か」です。バッチで十分な処理をストリーム化すると、運用の複雑さとインフラコストだけが増えます。不正検知や異常検知など「遅延が損失に直結する」ユースケースから始め、ウィンドウ設計とウォーターマークの2つを押さえれば、ストリーム処理の恩恵を着実に得られます。