Kafkaでイベントを流す土台はできた、次は「そのイベントをどう処理するか」が問題になります。1分ごとの注文を地域別に集計したい、5分間に発生した異常パターンを検知したい、複数のイベントを相関させたい。こうした本格的なストリーム処理を担うのがApache Flinkです。
「真のストリーミング」(イベント単位処理)で設計されており、低遅延・高スループット・厳密な状態管理を同時に実現します。学習コストは高めですが、本格的なリアルタイム処理が必要な場面では第一選択になるOSSです。基本構造と使い方を整理します。
Flinkの基本構造
| コンポーネント | 役割 |
|---|---|
| JobManager | ジョブの調整・タスク配置 |
| TaskManager | 実体タスクを動かす |
| State Backend | 状態の永続化(RocksDB等) |
| Checkpoint | 定期的に状態をスナップショット |
| Source / Sink | Kafka、ファイル、DBとの入出力 |
Sparkに似たクラスタアーキテクチャですが、ストリーム処理に特化した状態管理とチェックポイント機能が中核です。「障害が起きても、最後のチェックポイントから処理を再開する」のがFlinkの安心感の源です。
DataStream API:Javaコードで書く
// Kafkaから注文イベントを読み、1分窓で売上集計
DataStream<Order> orders = env.fromSource(
KafkaSource.builder()
.setBootstrapServers("localhost:9092")
.setTopics("orders")
.setDeserializer(new OrderDeserializer())
.build(),
WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(10)),
"kafka-source"
);
DataStream<RevenueByMinute> revenue = orders
.keyBy(Order::getCustomerId)
.window(TumblingEventTimeWindows.of(Time.minutes(1)))
.aggregate(new RevenueAggregator());
revenue.sinkTo(new SnowflakeSink());
「Kafkaから読み」「customer_idで分割」「1分窓で集計」「Snowflakeに書く」という流れがコードで明確に書けます。Watermarkで遅延イベントへの対処も組み込まれます。
Flink SQL:SQLで書ける
FlinkはSQL APIも提供しており、ストリーム処理をSQLで書けます。学習コストが大幅に下がります。
-- Kafkaソースを宣言
CREATE TABLE orders (
order_id BIGINT,
customer_id BIGINT,
amount DECIMAL(10,2),
ordered_at TIMESTAMP(3),
WATERMARK FOR ordered_at AS ordered_at - INTERVAL '10' SECOND
) WITH (
'connector' = 'kafka',
'topic' = 'orders',
'properties.bootstrap.servers' = 'localhost:9092',
'format' = 'json'
);
-- 1分窓で売上集計
SELECT
TUMBLE_START(ordered_at, INTERVAL '1' MINUTE) AS window_start,
customer_id,
SUM(amount) AS revenue
FROM orders
GROUP BY TUMBLE(ordered_at, INTERVAL '1' MINUTE), customer_id;
クラウドDWHでSQLを書き慣れていれば、Flink SQLは比較的取っ付きやすいです。Decodable・Aiven for Apache Flink・Confluent Cloudのマネージド版でFlink SQLが提供されており、運用負担を下げて始められます。
状態管理と Checkpoint
Flinkの真骨頂が「状態管理」です。ジョブが保持する集計値や、過去イベントの記憶を、RocksDB等の永続化ストアに保存しながら処理します。Checkpointで定期的に状態をスナップショットし、障害時にそこから復旧します。
| State Backend | 特徴 |
|---|---|
| HashMap | JVMメモリ。小さな状態に |
| RocksDB | ローカルディスク+圧縮。大規模状態に |
| External | S3等にCheckpoint保存(推奨) |
「複数イベントを跨いだ集計や相関」が必要な処理では、状態管理の堅牢さが運用品質を左右します。Flinkがこの領域で他のストリーム処理エンジンと差別化される点です。
Spark Streamingとの違い
| Flink | Spark Streaming(Structured Streaming) | |
|---|---|---|
| 処理モデル | 真のストリーミング(イベント単位) | マイクロバッチ(短いバッチを連続) |
| 遅延 | サブ秒〜秒 | 秒〜数十秒 |
| 状態管理 | 強力(RocksDB標準) | あり(Checkpointと統合) |
| 学習コスト | 高 | SparkユーザーならX低 |
| 本番実績 | 大規模本番で多数 | Sparkエコシステム内で多い |
Sparkでバッチを書き慣れているチームが軽い準リアルタイムを始めるならSpark Streaming、本格的な低遅延・複雑な状態管理が要件ならFlink、と分かれます。
マネージドの選択肢
| サービス | 特徴 |
|---|---|
| Ververica Platform | Flink本家系(Alibaba傘下)のエンタープライズ版 |
| AWS Managed Service for Apache Flink | AWSのマネージド(旧Kinesis Data Analytics for Flink) |
| Confluent Cloud Flink | ConfluentによるFlink SQLマネージド |
| Decodable | Flink SQL中心のマネージドサービス |
| Aiven for Apache Flink | マルチクラウド対応のマネージド |
Flinkは特にOSS自社運用が重く、クラスタの管理、Checkpointストレージ、ジョブのスケーリング設計が要る。マネージドが現実的な選択になりつつある。
運用上のハマりどころ
- 状態のサイズが爆発:KeyByの粒度を誤ると、状態がメモリ・ディスクを食い潰す。Key設計に経験が要る。
- Watermarkの設定:遅延イベントへの対処はWatermarkで制御するが、適切な値の見極めが難しい。
- Checkpoint間隔と障害復旧時間:間隔を短くすると安心だがオーバーヘッド、長くすると復旧時間が伸びる。バランス調整が必要。
- ジョブのバージョンアップ:状態スキーマが変わると、既存Checkpointから復旧できない。Savepoint運用が必須。
向く・向かない場面
- 向く:本格的な低遅延処理、複雑な状態管理が必要、CEP(複合イベント処理)、不正検知、リアルタイムアラート、CDC+複雑な変換
- 向かない:シンプルなリアルタイムビュー(→Materialize)、SQLで完結する集計、運用人員が薄い
まとめ
- Apache Flinkは「真のストリーミング」を実現する分散処理エンジン。
- 状態管理とCheckpointが中核で、複雑な処理を低遅延・堅牢に実行できる。
- DataStream API(Java)とFlink SQL(SQL)の両方で書ける。
- Spark Streamingとは「マイクロバッチか真のストリーミングか」が大きな違い。
- OSS自社運用は重く、Decodable等のFlink SQLマネージドから始めるのが現実的。
全体像はバッチ vs ストリーミングの選び方、隣接の選択肢はKafka とは・Materialize とはにあります。Flink導入や設計の壁打ちは、DE-STKの初回相談(30分・無料)もご利用ください。
よくある質問(FAQ)
Q. Flinkの学習コストはどの程度?
A. ストリーム処理の概念(時間窓・Watermark・状態管理)に慣れる必要があり、Java/Scalaの経験があっても2〜3ヶ月の本格的な学習期間が要る。Flink SQLから入れば、SQLが書ける人なら数週間で基本的なジョブが組めるレベルになる。新規導入なら、Flink SQLで始めて、必要に応じてDataStream APIへ降りる順序がコスト効率が良い。
Q. Flinkでデータウェアハウスに書き込めますか?
A. 公式・コミュニティ製のSinkで、Snowflake、BigQuery、Iceberg、Delta Lakeへの書き込みが可能です。リアルタイム処理の結果をDWHに永続化する典型構成です。クラウドDWHの基本はクラウドDWH入門、Icebergへの書き込みはApache Iceberg とはを参照してください。
Q. Flinkのジョブを安全にアップグレードする方法は?
A. Savepointを取って、新しいバージョンのジョブをそのSavepointから起動するのが定石です。状態スキーマに互換性があれば、ジョブのコード変更後も状態を引き継いで処理を続けられます。互換性がない変更は事前にテストし、必要なら状態移行ロジックを準備します。本番運用ではジョブのリリースサイクルとSavepoint運用を組織で標準化します。
Q. Flinkを使わずにストリーミング処理する選択肢は?
A. シンプルなリアルタイムSQL集計ならMaterializeが代替になります。Sparkユーザーなら Spark Structured Streaming、Kafkaの軽い処理だけならKafka Streams(Javaライブラリ)が選択肢です。「Flinkほどの本格機能が要らない」「もっと素早く始めたい」場合は、これらの軽量代替を検討してください。