- Published on
ストリーム処理 2026 完全ガイド - Kafka Streams・Flink SQL・RisingWave・Materialize・Arroyo・ksqlDB・Bytewax・Decodable 徹底解説
- Authors

- Name
- Youngju Kim
- @fjvbn20031
プロローグ — 「リアルタイムでお願い」という一言の重さ
2026年のあるフィンテックの会議室。
PM: 「リアルタイム不正検知ダッシュボード作れますよね?」 エンジニア: 「リアルタイムってどのくらい?」 PM: 「えっと... すぐに?」 エンジニア: 「1秒?100ミリ秒?それとも5分?」
この短い会話に 2026年のストリーム処理のすべてが詰まっている。一方には「Kafka からデータを取ってくればリアルタイムだ」という漠然とした期待があり、もう一方にはウィンドウ、ウォーターマーク、exactly-once、バックプレッシャー、状態バックアップを毎日触っているエンジニアのため息がある。その間を Flink、Kafka Streams、RisingWave、Materialize、Arroyo、ksqlDB、Bytewax が埋めている。
2026年現在、ストリーム処理は三つのパラダイムに分かれる。プログラミングフレームワーク(Flink、Kafka Streams、Bytewax)、SQL ストリーミング DB(RisingWave、Materialize、ksqlDB)、そしてマネージド SaaS(Decodable、Confluent Cloud Flink、Aiven Flink、Quix)。さらにその上に状態管理モデルの二軸が重なる — 組み込み RocksDB vs S3 上の Disaggregated State。
本記事はその全地形を一気に整理する。Flink 2.0 の Disaggregated State Backend から、RisingWave 2.x の Postgres ワイア、Materialize の Differential Dataflow、Arroyo の Rust SQL エンジン、ksqlDB の Confluent による収束、Bytewax の Python での飛躍、そして韓国・日本のビッグテックが何をどう使っているかまで。
1章 · 2026年ストリーム処理の地図 — Framework / Stream DB / Managed の 3 パラダイム
まず用語から。「ストリーム処理」という一語の中に違う三つが入っている。
| パラダイム | 意味 | 代表 | 利用者 |
|---|---|---|---|
| Stream Processing Framework | コードでトポロジーを書く(DataStream、KStream) | Flink、Kafka Streams、Bytewax、Beam | データエンジニア |
| Streaming Database | SQL でビューを定義、incremental に計算 | RisingWave、Materialize、ksqlDB | アナリスト、バックエンド |
| Managed Streaming SaaS | 上記をホスティング | Decodable、Confluent Cloud Flink、Quix | 小規模チーム |
2026年には境界が曖昧になった。Flink は Materialized Tables を追加し、RisingWave は Rust UDF を受け入れ、Kafka Streams は事実上 ksqlDB の後継として吸収されつつある。
それでも選択の出発点はパラダイムだ。次の意思決定ツリーを推奨する。
- 「Kafka トピック間のデータ変換と集計だけ必要」 → Kafka Streams(Java/Scala)または ksqlDB(SQL)。
- 「複雑なウィンドウ/ジョイン/CEP、非 Kafka ソース、ペタバイト級」 → Flink(SQL または DataStream API)。
- 「アプリは Postgres でクエリしたい、Materialized View が自動更新されてほしい」 → RisingWave または Materialize。
- 「Python データサイエンティストが直接使えなければ」 → Bytewax または Quix。
- 「運用したくない、SaaS で済ませたい」 → Decodable、Confluent Cloud Flink、Aiven Flink。
- 「Rust モノトーンワークロード、シングルバイナリ」 → Arroyo。
Flink がハンマーなら全ての問題が釘になる。2026年のベテラン曰く「秒間1万件のイベント、単純集計なら ksqlDB か Materialize で十分だ。Flink クラスター運用は後悔する」。
2章 · ストリーミング vs バッチ vs マイクロバッチ — レイテンシのスペクトラム
まずパラダイムそのものから。
| モデル | 処理単位 | レイテンシ | 代表 |
|---|---|---|---|
| Batch | 大きなデータセット一括 | 分〜時間 | Spark batch、Hive、dbt |
| Micro-batch | 小バッチを定期実行 | 秒〜分 | Spark Structured Streaming、Trino on Iceberg |
| True streaming | イベント1件ずつ | ms〜秒 | Flink、Kafka Streams、RisingWave |
| Continuous query | ビュー結果を incremental 更新 | 秒〜分 | Materialize、RisingWave、Snowflake Dynamic Tables |
Spark Structured Streaming のマイクロバッチは毎回小さなバッチジョブを回す。P99 は通常 1〜10秒。Flink は真の record-at-a-time(または mini-batch モード)で P99 100ms 未満が可能。だから HFT、ゲームマッチング、不正検知は Flink/Kafka Streams、分析ダッシュボードは Materialize/RisingWave、日次レポートは Spark/Trino へと流れる。
核心は「1秒以内のリアルタイムがビジネス価値を生むか」という問いだ。多くの BI ダッシュボードは 5分遅延でも問題ない。それならマイクロバッチで十分。本物のストリーム処理は「1秒の遅延が売上を左右する」場所でのみ必要だ。
3章 · Apache Flink 2.0 — Disaggregated State と Materialized Tables
Apache Flink は 2014年の Stratosphere プロジェクトに始まり、data Artisans(現 Ververica、Alibaba 買収)が主導。2025年3月にリリースされた Flink 2.0 が転換点だ。本章では Flink の SQL/Table API/DataStream API/状態/ウォーターマーク/exactly-once を一気に整理する。
Flink 2.0 の主要変更。
- Disaggregated State Backend (ForSt): state を broker のディスクではなく S3/GCS に置き、ローカルキャッシュで hot データを保持。状態にも tiered storage が来た。
- Async State API: 状態アクセスを非同期化し P99 を改善。
- Materialized Tables (FLIP-435): SQL でビュー定義 → バックグラウンドで incremental refresh。RisingWave/Materialize の領域を正式に吸収。
- Adaptive Batch Scheduler のデフォルト化: ストリームとバッチを同じエンジンで。
- Java 17 ベースライン、Scala 2.13 移行完了、Python 3.12 対応。
Flink のアーキテクチャは 4層。
| 層 | 責務 | 例 |
|---|---|---|
| Flink SQL | ANSI SQL、Catalog、Hive 互換 | CREATE TABLE orders ... |
| Table API | リレーショナル API(Java/Scala/Python) | table.groupBy("user").select(...) |
| DataStream API | 低レベル変換 | dataStream.map().keyBy().window() |
| Stateful Functions / ProcessFunction | 最低レベル、直接状態 | RichFlatMapFunction |
Flink SQL で Kafka トピックを読み込みジョインする例。
CREATE TABLE orders (
order_id BIGINT,
user_id BIGINT,
amount DECIMAL(10,2),
event_time TIMESTAMP_LTZ(3),
WATERMARK FOR event_time AS event_time - INTERVAL '5' SECOND
) WITH (
'connector' = 'kafka',
'topic' = 'orders',
'properties.bootstrap.servers' = 'kafka:9092',
'scan.startup.mode' = 'earliest-offset',
'format' = 'avro-confluent',
'avro-confluent.schema-registry.url' = 'http://schema-registry:8081'
);
CREATE TABLE users (
user_id BIGINT,
segment STRING,
PRIMARY KEY (user_id) NOT ENFORCED
) WITH (
'connector' = 'jdbc',
'url' = 'jdbc:postgresql://pg:5432/app',
'table-name' = 'users'
);
SELECT
segment,
TUMBLE_START(event_time, INTERVAL '5' MINUTE) AS window_start,
SUM(amount) AS revenue
FROM orders o
JOIN users u ON o.user_id = u.user_id
GROUP BY segment, TUMBLE(event_time, INTERVAL '5' MINUTE);
この一つのクエリに Flink の核心が全部入っている — Kafka source、JDBC lookup、watermark、tumbling window、group-by aggregate。
4章 · Flink DataStream API + Stateful Functions
Flink SQL では表現できない領域もある。複雑な状態機械、カスタムパーティショニング、動的ルーティング、CEP など。そのとき DataStream API の出番だ。
Java の例 — ユーザー別セッションウィンドウとアラート。
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.enableCheckpointing(30_000); // 30s
DataStream<Event> events = env.fromSource(
KafkaSource.<Event>builder()
.setBootstrapServers("kafka:9092")
.setTopics("clicks")
.setStartingOffsets(OffsetsInitializer.earliest())
.setValueOnlyDeserializer(new EventDeserializer())
.build(),
WatermarkStrategy.<Event>forBoundedOutOfOrderness(Duration.ofSeconds(5))
.withTimestampAssigner((e, ts) -> e.eventTimeMs()),
"kafka-source"
);
events
.keyBy(Event::userId)
.window(EventTimeSessionWindows.withGap(Time.minutes(10)))
.process(new ProcessWindowFunction<Event, Alert, Long, TimeWindow>() {
@Override
public void process(Long userId, Context ctx, Iterable<Event> elems, Collector<Alert> out) {
int count = 0;
for (Event e : elems) count++;
if (count > 100) out.collect(new Alert(userId, count, "abusive"));
}
})
.sinkTo(KafkaSink.<Alert>builder()
.setBootstrapServers("kafka:9092")
.setRecordSerializer(...)
.setDeliveryGuarantee(DeliveryGuarantee.EXACTLY_ONCE)
.build());
env.execute("session-alert");
形は keyBy → window → process。keyBy が同一キーのイベントを同タスクにルーティング、window が時間/セッションでまとめ、process がウィンドウ単位で結果を出す。
状態は RichFunction 経由でアクセス。
public class FraudDetector extends KeyedProcessFunction<Long, Tx, Alert> {
private transient ValueState<Double> lastAmount;
private transient ListState<Tx> recentTxs;
@Override
public void open(Configuration cfg) {
lastAmount = getRuntimeContext().getState(
new ValueStateDescriptor<>("last", Double.class));
recentTxs = getRuntimeContext().getListState(
new ListStateDescriptor<>("recent", Tx.class));
}
@Override
public void processElement(Tx tx, Context ctx, Collector<Alert> out) throws Exception {
Double prev = lastAmount.value();
if (prev != null && tx.amount() > prev * 10) {
out.collect(new Alert(tx.userId(), "amount-spike"));
}
lastAmount.update(tx.amount());
recentTxs.add(tx);
}
}
Flink は ValueState、ListState、MapState、ReducingState、AggregatingState を提供する。全て keyed scope で、同じキーのイベント同士でのみ共有される。
5章 · Flink 状態、チェックポイント、exactly-once
Flink の強みは exactly-once セマンティクスだ。Kafka source + Kafka sink のとき、障害が起きても結果に重複も欠落もなく正確に 1回適用される。どうやって?
核心は Chandy-Lamport アルゴリズムに基づく分散スナップショット。
- JobManager が定期的に checkpoint barrier を source に注入。
- Barrier がデータと共に dataflow を下流に流れる。
- 各 operator が barrier を受け取ると自身の状態をスナップショット。
- Sink が barrier を受け取ると sink 固有の commit(Kafka は transactional producer commit)。
- 全 operator が ack するとチェックポイント完了。
障害時。
- 最後の成功した checkpoint から全 operator の状態を復元。
- Source は当該 checkpoint の offset から再読込。
- Sink は transactional producer なので committed transaction のみ外部に見える。
設定例。
env.enableCheckpointing(60_000);
env.getCheckpointConfig().setCheckpointStorage("s3://flink-state/checkpoints");
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(30_000);
env.getCheckpointConfig().setCheckpointTimeout(300_000);
env.getCheckpointConfig().enableUnalignedCheckpoints();
env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
env.setStateBackend(new EmbeddedRocksDBStateBackend());
Flink 2.0 の ForSt(Disaggregated state)は RocksDB を S3 にバックアップする方式。状態がペタバイト規模でも broker ディスクに縛られない。
6章 · Flink ウィンドウ — Tumbling / Sliding / Session / Custom
ストリーム処理の中心的抽象はウィンドウだ。無限ストリームを有限のチャンクに切る方法。
| ウィンドウ | 意味 | 例 |
|---|---|---|
| Tumbling | 重ならない固定サイズ | 5分単位の売上 |
| Sliding | 重なる固定サイズ | 30秒ごとに直近5分平均 |
| Session | 非アクティブギャップ基準 | 30分無活動でセッション終了 |
| Global | 全体無限 | 全体カウント(状態無限増加のリスク) |
Tumbling の例(Flink SQL)。
SELECT
TUMBLE_START(event_time, INTERVAL '5' MINUTE) AS w_start,
COUNT(*) AS cnt
FROM clicks
GROUP BY TUMBLE(event_time, INTERVAL '5' MINUTE);
Sliding(HOP)。
SELECT
HOP_START(event_time, INTERVAL '30' SECOND, INTERVAL '5' MINUTE) AS w_start,
AVG(latency) AS avg_latency
FROM requests
GROUP BY HOP(event_time, INTERVAL '30' SECOND, INTERVAL '5' MINUTE);
Session。
SELECT
user_id,
SESSION_START(event_time, INTERVAL '30' MINUTE) AS s_start,
COUNT(*) AS events_in_session
FROM user_events
GROUP BY user_id, SESSION(event_time, INTERVAL '30' MINUTE);
ウィンドウ選択の基準。
- 固定周期レポート(時/日別): Tumbling。
- 移動平均、ホットメトリクス: Sliding(slide を小さく)。
- ユーザー行動分析: Session。
- 不定区間の状態機械: ProcessFunction + timer。
7章 · イベント時刻 vs 処理時刻 — ウォーターマークの本質
ストリーム処理で最も難しい概念。「イベント時刻」はイベントが実際に発生した時刻、「処理時刻」はシステムがそれを見た時刻。二つは違う。
- モバイルアプリがオフラインのときに発生したイベントが10分後に到着。
- ネットワーク遅延で一部が遅れて到着。
- システムが一時停止して目覚めた。
ウォーターマーク (watermark) は「この時刻より前のイベントはもう来ないと仮定してよい」というシグナル。ウォーターマークはウィンドウクローズ、結果 emit、late data 分離のトリガーだ。
Flink のウォーターマーク戦略。
WatermarkStrategy.<Event>forBoundedOutOfOrderness(Duration.ofSeconds(10))
.withTimestampAssigner((event, ts) -> event.eventTimeMs())
.withIdleness(Duration.ofMinutes(1));
forBoundedOutOfOrderness(10s) の意味は「私が見た最大イベント時刻が T なら、T-10s より前のイベントだけ処理する。それ以降に到着したら late data」。
Late data 処理。
SingleOutputStreamOperator<Result> main = stream
.keyBy(...)
.window(TumblingEventTimeWindows.of(Time.minutes(5)))
.allowedLateness(Time.minutes(2))
.sideOutputLateData(lateTag)
.process(...);
DataStream<Event> late = main.getSideOutput(lateTag);
ウォーターマークは正確性と遅延のトレードオフだ。短ければ結果は早いが late data が多く、長ければ正確だが結果が遅い。
8章 · CEP — Complex Event Processing
CEP はイベントパターンマッチングだ。例:「ログイン失敗 5回連続 → アカウントロック」「5分以内に決済 → 返金 → 決済 → 不正疑い」。
Flink CEP の例。
Pattern<LoginEvent, ?> pattern = Pattern.<LoginEvent>begin("first")
.where(SimpleCondition.of(e -> !e.success()))
.next("repeat")
.where(SimpleCondition.of(e -> !e.success()))
.times(4)
.within(Time.minutes(5));
PatternStream<LoginEvent> ps = CEP.pattern(events.keyBy(LoginEvent::userId), pattern);
DataStream<Alert> alerts = ps.select(match -> {
LoginEvent last = match.get("repeat").get(3);
return new Alert(last.userId(), "5-fail-in-5min");
});
CEP は Flink CEP、Esper(長い歴史)、Drools Fusion(ルールエンジン系)が代表。不正検知、IDS、取引ルール、IoT アラートの核心。
CEP の難しさは状態管理。5分のパターンなら 5分分の部分マッチを全部持つ必要がある。トラフィックの多い場所で state が爆発する。解決策は partition by key + state TTL + パターン単純化。
9章 · Kafka Streams 4.0 — ライブラリとしてのストリーム処理
Kafka Streams は Confluent が Kafka 0.10(2016)に追加したライブラリだ。Flink が「分散クラスターにジョブを投入」なら、Kafka Streams は「自分の Spring Boot アプリに import して使うライブラリ」。
2025年リリースの Kafka Streams 4.0 のハイライト。
- Share Groups (KIP-932) との統合 — 同じトピックをキューのように消費。
- Async Processing API — non-blocking I/O フレンドリー。
- State Store on RocksDB 7.x — 圧縮向上、faster recovery。
- Java 17 ベースライン、実験的 GraalVM Native Image サポート。
- Kafka Streams DSL 安定化 — KTable.join、KStream-KTable join のバリエーション拡充。
Kafka Streams の二つの抽象。
- KStream: 無限の record stream(insert-only)。
- KTable: キー別の最新値を保持する changelog ベースのテーブル。
ワードカウントの基本例(Java)。
Properties props = new Properties();
props.put(StreamsConfig.APPLICATION_ID_CONFIG, "wc-app");
props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka:9092");
props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());
props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());
StreamsBuilder builder = new StreamsBuilder();
KStream<String, String> source = builder.stream("text-input");
KTable<String, Long> counts = source
.flatMapValues(v -> Arrays.asList(v.toLowerCase().split("\\W+")))
.groupBy((k, v) -> v)
.count();
counts.toStream().to("word-count-output", Produced.with(Serdes.String(), Serdes.Long()));
KafkaStreams streams = new KafkaStreams(builder.build(), props);
streams.start();
Kafka Streams の魅力はただのライブラリであること。同じ jar を N 個立てれば自動でパーティションを分け合う(Kafka consumer group + 内部リバランス)。別途クラスターマネージャ不要。Spring Boot、Quarkus、Micronaut どこにでも埋め込める。
10章 · Kafka Streams の状態 + Interactive Queries
KTable と aggregate は state store に保存される(デフォルト RocksDB、in-memory も可)。そしてその状態を外部から直接クエリできる(Interactive Queries)。
Interactive Queries の例。
ReadOnlyKeyValueStore<String, Long> store = streams.store(
StoreQueryParameters.fromNameAndType("word-counts", QueryableStoreTypes.keyValueStore())
);
Long count = store.get("kafka");
ここで強力なパターン — Streams App = マイクロサービス。Kafka からデータを読み、自前 RocksDB に集計結果を保存、REST API で外部に公開。別途 OLAP DB なしでリアルタイムビューを提供。
代償は分散 state の複雑さ。どのキーがどのインスタンスにあるか知る必要がある。Kafka Streams は metadataForKey() API でそれを教えてくれ、gRPC/REST ルーティングは自分で書く必要がある。
GlobalKTable で小さな lookup テーブルを全インスタンスにレプリケートすることもできる(全パーティションを全インスタンスが読む)。
Kafka Streams は **「Kafka にあるデータのみ」**を処理する。外部 JDBC、REST API とのジョインは限定的(Kafka Connect で先に sourcing する必要)。これが Flink との最大の違い。
11章 · ksqlDB 0.30 — SQL on Kafka の興亡
ksqlDB は Confluent が 2017年に公開した「Kafka 上の SQL データベース」。内部的に Kafka Streams を使用。一行 SQL クエリを投げるとバックグラウンドのストリーミングジョブが回る。
CREATE STREAM orders (
order_id BIGINT KEY,
user_id BIGINT,
amount DECIMAL(10,2)
) WITH (KAFKA_TOPIC='orders', VALUE_FORMAT='AVRO');
CREATE TABLE user_revenue AS
SELECT user_id, SUM(amount) AS total
FROM orders
GROUP BY user_id
EMIT CHANGES;
SELECT * FROM user_revenue WHERE user_id = 42 EMIT CHANGES;
最後の EMIT CHANGES は「継続的に結果の変化を push」という意味。これがストリーミング SQL の本質だ。
ksqlDB 0.30(2025)は事実上最後のメジャーリリース。Confluent が 2025年初頭に発表した方向は 「ksqlDB → Flink SQL」。すなわち Confluent Cloud の SQL ストリーミングは Flink に統合され、ksqlDB はメンテナンスモードへ。新規プロジェクトは Flink SQL 推奨。
それでも ksqlDB は多くの場所で稼働中だ。マイグレーションパスが重要な理由。
12章 · RisingWave 2.x — Postgres ワイア上のストリーミング DB
RisingWave は 2021年に Singularity Data(現 RisingWave Labs)が始めた Rust ベースのストリーミング DB。2025年リリースの RisingWave 2.0 を一行で要約すると「Postgres のように見えるが中で streaming SQL が走る」。
主要特徴。
- Postgres wire protocol 100% 互換: psql、JDBC、ORM がそのまま動く。
- Materialized Views が一級市民:
CREATE MATERIALIZED VIEWが incremental streaming ジョブ。 - Rust エンジン、thread-per-core: 低オーバーヘッド、安定した P99。
- S3 に state オフロード: 初日から Disaggregated state。
- Cluster + Cloud + Standalone のデプロイモード。
- CDC source 内蔵: Postgres、MySQL の binlog 直読。
基本使用例。
CREATE SOURCE orders_source (
order_id BIGINT,
user_id BIGINT,
amount NUMERIC,
event_time TIMESTAMPTZ
) WITH (
connector = 'kafka',
topic = 'orders',
properties.bootstrap.server = 'kafka:9092',
scan.startup.mode = 'earliest'
) FORMAT PLAIN ENCODE JSON;
CREATE MATERIALIZED VIEW hourly_revenue AS
SELECT
date_trunc('hour', event_time) AS hour,
SUM(amount) AS revenue,
COUNT(*) AS orders
FROM orders_source
GROUP BY 1;
SELECT * FROM hourly_revenue ORDER BY hour DESC LIMIT 24;
最後の SELECT が魔法だ。RisingWave は hourly_revenue をバックグラウンドで incremental に更新しており、クエリはその結果の現在状態を即座に返す。なので OLAP DB のようにユーザーが直接ダッシュボードでクエリしてもよい。
RisingWave 2.x の新機能。
- Iceberg Sink + Iceberg Source: データレイクと直結。
- Python / JavaScript / Rust の UDF。
- Subscription: Postgres LISTEN/NOTIFY のような変更購読。
- Snowflake / BigQuery / Redshift sink。
13章 · Materialize — Differential Dataflow の商用化
Materialize は 2019年に Frank McSherry(Microsoft Research、Naiad/Differential Dataflow の著者)と Arjun Narayan が創業。一行で要約すると「本物の incremental view maintenance」。
主要な違い。
- Differential Dataflow エンジン: 1996年から研究されている本物の incremental 計算。delta だけ伝播。
- Postgres ワイア: RisingWave のように psql/JDBC 互換。
- SQL 99% カバー: Postgres 互換 dialect、recursive CTE まで。
- Strict serializability: 全クエリが一貫したスナップショットを見る。
- 2024年に Cloud リリース: セルフホストも可能だが事実上 SaaS 優先。
基本例。
CREATE SOURCE orders FROM KAFKA BROKER 'kafka:9092' TOPIC 'orders'
FORMAT AVRO USING CONFLUENT SCHEMA REGISTRY 'http://schema-registry:8081'
ENVELOPE NONE;
CREATE MATERIALIZED VIEW revenue_by_segment AS
SELECT
u.segment,
SUM(o.amount) AS revenue
FROM orders o
JOIN users u ON o.user_id = u.user_id
GROUP BY u.segment;
SELECT * FROM revenue_by_segment;
Materialize の差別性は任意の SQL を incremental にすること。一般的なストリーミング SQL は group by aggregate、window などの定型パターンだけ incremental。Materialize は join、subquery、recursive CTE まで incremental。
代償は state メモリ。Differential Dataflow は基本インメモリ(ディスク spill オプション追加中)。なので大規模は RisingWave、複雑な SQL は Materialize が強み。
14章 · Arroyo — Rust で書き直された Flink SQL
Arroyo は 2023年に Micah Wylde(Lyft Streaming 出身)が始めた Rust ベースのストリーミングエンジン。一行で要約すると「Flink SQL 互換 + シングルバイナリ + 速い」。
主要特徴。
- Rust エンジン: JVM なしのシングルバイナリ。
- Arroyo SQL = Flink SQL 互換サブセット。
- Web UI 優先: ジョブ作成と監視が SaaS のよう。
- S3 state: tiered、RocksDB なし。
- Kubernetes operator 提供。
CLI でジョブ作成。
docker run -p 8000:8000 ghcr.io/arroyosystems/arroyo:latest
Web UI で SQL 入力。
CREATE TABLE events (
user_id BIGINT,
event_type TEXT,
amount FLOAT,
ts TIMESTAMP
) WITH (
connector = 'kafka',
bootstrap_servers = 'kafka:9092',
topic = 'events',
type = 'source',
format = 'json',
'event_time_field' = 'ts',
'watermark_field' = 'ts'
);
CREATE TABLE sinks WITH (connector = 'kafka', topic = 'alerts', type = 'sink', format = 'json');
INSERT INTO sinks
SELECT user_id, SUM(amount) AS total
FROM events
WHERE event_type = 'purchase'
GROUP BY user_id, TUMBLE(INTERVAL '5' MINUTE);
Arroyo は 2026年時点で production 採用が増えている。**「Flink を運用したくない、かつ Confluent に縛られたくない」**チームがよく選ぶ。Lyft、Reddit、Stripe の一部チームで利用中。
弱点は SQL カバレッジ。Arroyo SQL は Flink SQL のサブセットなので一部関数が無い。急速に追いついているが未到達。
15章 · Bytewax — Python でストリーム処理
Bytewax は 2022年に Bytewax(会社)が始めた Python ストリーミングフレームワーク。一行で要約すると「Flink に似ているが Python で書く」。
主要特徴。
- Pure Python API: データサイエンティストが直接書ける。
- Rust コア + PyO3: 性能は Rust、ユーザーコードは Python。
- PyData 統合: NumPy、Pandas、scikit-learn を直接。
- Connectors: Kafka、Redpanda、Kinesis、S3、Iceberg、ClickHouse など。
基本例 — ワードカウント。
from bytewax.dataflow import Dataflow
from bytewax.connectors.kafka import KafkaSource, KafkaSink
from bytewax import operators as op
from bytewax.connectors.stdio import StdOutSink
flow = Dataflow("word-count")
stream = op.input("kafka-in", flow, KafkaSource(
brokers=["kafka:9092"], topics=["text"]
))
words = op.flat_map("split", stream, lambda msg: msg.value.decode().split())
keyed = op.key_on("key", words, lambda w: w)
counts = op.stateful_map("count",
keyed,
lambda: 0,
lambda count, word: (count + 1, (word, count + 1))
)
op.output("stdout", counts, StdOutSink())
Bytewax の強みは ML 推論との統合。PyTorch / scikit-learn / Hugging Face モデルをそのままストリームに適用できる。
import torch
from transformers import pipeline
clf = pipeline("text-classification", model="distilbert-base-uncased")
def classify(text):
return clf(text)[0]
stream = op.input(...)
labeled = op.map("classify", stream, classify)
op.output("sink", labeled, ...)
これを Flink でやると Python UDF 経由になり、モデルロードが非効率。Bytewax は同じ Python プロセス内なので速く直感的。
弱点は運用成熟度。Flink のような巨大クラスター、数年検証された exactly-once を期待してはいけない。100〜1000 events/sec 規模、データサイエンスパイプラインに適している。
16章 · Apache Beam — 統合 API の約束と限界
Apache Beam は 2016年に Google が Cloud Dataflow のモデルをオープンソース化したもの。一行で「Stream と Batch を同じ API で」。
中心アイデア。
- PTransform / PCollection / Pipeline 抽象。
- Runner 分離: Flink Runner、Spark Runner、Dataflow Runner、Samza Runner。
- Java / Python / Go SDK。
import apache_beam as beam
from apache_beam.options.pipeline_options import PipelineOptions
with beam.Pipeline(options=PipelineOptions()) as p:
(p
| 'Read' >> beam.io.ReadFromKafka(...)
| 'Window' >> beam.WindowInto(beam.window.FixedWindows(60))
| 'Count' >> beam.combiners.Count.PerKey()
| 'Write' >> beam.io.WriteToBigQuery(...))
同じコードを Flink Runner でも、Dataflow Runner でも動かせる。理論上は。
実際には Runner ごとにサポート機能が違い、デバッグが難しく、ネイティブ API に比べて一段の抽象化が余分にある。2026年時点で Beam は Google Cloud Dataflow を使うチームが主に使う。マルチクラウドの約束を真剣に追求するケースは稀だ。
17章 · Decodable、Confluent Cloud Flink、Aiven Flink — Managed Flink 比較
直接 Flink を運用するのは大変だ。だからマネージドが成熟した。
| 提供元 | エンジン | 価格モデル | 特徴 |
|---|---|---|---|
| Confluent Cloud Flink | Flink 1.20+ | Compute Unit + データ処理 | Schema Registry / Kafka 統合が最高 |
| Aiven for Flink | Flink(Apache) | インスタンス時間 + ストレージ | マルチクラウド、Karapace |
| Decodable | Flink + 自前 OS | スループット課金 | 「5分でパイプライン」、connector 豊富 |
| Ververica Platform Cloud | Flink + Ververica Enterprise | インスタンス | Flink オリジナル企業、オンプレ強し |
| Striim | 自前エンジン(Flink ベース一部) | ライセンス | CDC + ストリーミング統合 |
| Amazon MSF | Flink | 時間 + スループット | AWS Managed Service for Apache Flink |
2026年の推奨ガイド。
- Kafka 中心フルスタック: Confluent Cloud Flink。
- 安価、マルチクラウド OSS: Aiven Flink。
- クイックスタート、GUI 優先: Decodable。
- AWS ロックイン OK: MSF。
- オンプレ / エンタープライズサポート: Ververica Platform。
Decodable の魅力は YAML でパイプライン定義 → 即実行。小規模チームで「今日中に CDC パイプラインを作る」が可能。
sources:
- name: orders-kafka
type: kafka
bootstrap_servers: kafka:9092
topic: orders
pipelines:
- name: enrich-orders
sql: |
SELECT o.*, u.segment
FROM orders o
JOIN users u ON o.user_id = u.user_id
sinks:
- name: enriched-snowflake
type: snowflake
table: enriched_orders
18章 · Quix、Pulsar Functions、Memphis、Redpanda Connect — 軽量オプション
大きな Flink がオーバーキルなケースの選択肢。
Quix Streams — Python ライブラリ。Bytewax よりさらに軽量、Kafka に特化。
from quixstreams import Application
app = Application(broker_address="kafka:9092")
events = app.dataframe(topic=app.topic("events"))
events["amount_x2"] = events["amount"] * 2
events.filter(lambda row: row["amount"] > 100).to_topic(app.topic("alerts"))
app.run()
Apache Pulsar Functions — Pulsar 内蔵。軽量な per-message transform。
def process(input, context):
return input.upper()
デプロイは pulsar-admin functions create 一発。
Memphis.dev / Superstream — Kafka 互換 OSS キュー、ストリーミング機能の一部を内蔵。
Redpanda Connect(旧 Benthos)— 強力な YAML ベース ETL。200以上の connector。
input:
kafka:
addresses: [kafka:9092]
topics: [events]
pipeline:
processors:
- mapping: |
root = this
root.processed_at = now()
root.amount_usd = this.amount * 0.93
output:
kafka:
addresses: [kafka:9092]
topic: events-processed
Redpanda Connect は「stream processor」よりも「stream ETL」に近い。ウィンドウ・ジョインは弱いが、変換・ルーティング・エンリッチメントは抜群。
19章 · Estuary Flow — CDC + ストリーミングの融合
Estuary Flow は 2023年から CDC ストリーミングを扱う SaaS。Kafka のようなメッセージブローカーなしで直接 source-to-sink ストリーミング。
特徴。
- Gazette(オープンソース log broker、Kafka 互換ではない)をバックボーンに。
- Captures: Postgres binlog、MongoDB oplog、MySQL、MSSQL CDC。
- Materializations: BigQuery、Snowflake、ClickHouse、Postgres sink。
- Derivations: SQL/TypeScript で変換定義。
captures:
acme/source-postgres:
endpoint:
connector:
image: ghcr.io/estuary/source-postgres:dev
config:
address: pg:5432
database: app
user: estuary
password: secret
bindings:
- resource: { table: orders, namespace: public }
target: acme/orders
Estuary のアイデンティティは「Kafka なしのストリーミング」。CDC → 変換 → DW までを単一 SaaS で。ClickHouse + ELT バックエンドを高速構築するチームに人気。
20章 · バックプレッシャー — ストリーミングが難しい理由 #1
バックプレッシャー (backpressure) は「コンシューマが追いつかないときどうするか」の問題。ストリーム処理の 80% は結局これをうまく扱うこと。
問題シナリオ。Kafka に毎秒10万件流入 → Flink が変換 → Elasticsearch に sink。ES が遅くなり毎秒5万件しか受け取らない。すると?
- Flink operator chain が全体で詰まる。
- 結局 Kafka source が fetch を止める → コンシューマラグ増加。
- メモリ/ディスクが徐々に埋まって OOM リスク。
対応パターン。
- 自然な backpressure(pull ベース): Flink/Kafka Streams は基本 pull ベースで backpressure を自然に伝播。
- バッファリング: Kafka 自体が巨大バッファ。データロスなくコンシューマがキャッチアップする時間を与える。
- Async I/O: Flink AsyncFunction で外部呼び出しを並列化。
- Drop / Sample: 本当に追いつかないなら一部イベントを drop(モニタリング・メトリクスは OK、決済は NG)。
- Scale out: パーティション増、コンシューマ増。
Flink のバックプレッシャーは Web UI の backpressure タブで色で見える(LOW/HIGH)。HIGH が数日続けばその operator がボトルネック。
21章 · スキーマ進化と Schema Registry
ストリーミングでスキーマ互換性は運用の核心。Avro/Protobuf + Schema Registry が標準パターン。
curl -X POST http://schema-registry:8081/subjects/orders-value/versions \
-H "Content-Type: application/vnd.schemaregistry.v1+json" \
-d '{
"schema": "{ \"type\": \"record\", \"name\": \"Order\", \"fields\": [{\"name\":\"order_id\",\"type\":\"long\"}] }"
}'
curl -X PUT http://schema-registry:8081/config/orders-value \
-H "Content-Type: application/vnd.schemaregistry.v1+json" \
-d '{"compatibility": "BACKWARD"}'
互換性モード。
- BACKWARD: 新スキーマで old データを読める(フィールド追加可、削除は default がある場合のみ)。
- FORWARD: 旧スキーマで新データを読める(フィールド削除可、追加は無視)。
- FULL: 双方向。
- NONE: 互換性チェックなし(危険)。
推奨: BACKWARD をデフォルトに。Producer は新スキーマで書き、Consumer は段階的にアップグレード。
22章 · 韓国ビッグテックのストリーム処理採用事例
韓国ビッグテックの実例(公開された技術ブログ・カンファレンス発表ベース)。
Coupang — Kafka + Flink + ksqlDB。リアルタイム価格決定、異常取引検出、検索クリック追跡。Disaggregated state 導入でペタバイト state 運用。2024年 Coupang Engineering Blog で Flink-on-Kubernetes 事例を共有。
NAVER 検索 — 自前ストリーム処理(Kafka Streams ベース)+ Flink SQL。検索トラフィックのリアルタイム統計、A/B テストメトリクス。自前 Schema Registry。
Kakao Pay / Kakao Bank — Flink + Kafka。取引リアルタイム分析、不正検知、決済ストリーム。2025年 if(kakao) で Flink CEP 不正パターン事例を発表。
NCsoft — Kafka Streams(Java)+ Flink。リアルタイムゲームマッチング、ログ分析、不正検知。ゲームトラフィックの特性上 P99 50ms 以下を要求。
ベミン(Woowa Brothers) — Kafka + Flink + Elasticsearch。リアルタイム配達位置、注文状態機械、異常パターン。2024年 WoowaCon で Flink-on-K8s 運用を共有。
Kakao Mobility — Kafka Streams + 自前処理。リアルタイムマッチング、位置追跡、動的価格。
Toss — Kafka + Flink + Druid。リアルタイム決済モニタリング、BI ダッシュボード。2025年 SLASH で Materialize 評価事例を共有(移行はまだ)。
NAVER Z(ZEPETO) — Kafka + Flink。仮想空間イベント処理、リアルタイム行動分析。
SK Telecom — Kafka + Spark Structured Streaming → Flink への段階的移行。通話品質・基地局メトリクス。
23章 · 日本ビッグテックのストリーム処理採用事例
Mercari — Kafka + Flink(GCP Dataflow も一部)。リアルタイム不正検知(CEP 多用)、レコメンド、商品検索インデキシング。2025年 Mercari Engineering Blog で Flink CEP 不正パターン事例。
LINE ヤフー — 自前 Kafka + Flink + ksqlDB。リアルタイムプッシュ通知ルーティング、トレンド検出、広告入札。2024年 LY Tech Conf で Flink-on-K8s 事例。
楽天 — Kafka + Spark Streaming → Flink + RisingWave 評価中。リアルタイム価格、レコメンド。グローバルマルチリージョン。
SmartNews — Kafka + Flink。リアルタイムニューストレンド、ユーザー行動追跡。広告入札に CEP。
サイバーエージェント — Kafka + Flink。広告入札、動画視聴分析、AbemaTV リアルタイム視聴メトリクス。
ZOZO — Kafka + Flink。商品検索インデキシング、レコメンド、ユーザー行動。
DeNA — Kafka + Spark Streaming + Flink。ゲーム不正検知、決済モニタリング、マーケティング分析。
LINE Pay — Flink + Kafka。取引モニタリング、不正検知。
ミクシィ — Kafka + Flink(特にモバイルゲーム分野)。リアルタイムイベントカウンター、マッチング。
NTT Communications — Apache Beam + Dataflow。IoT テレメトリ。
24章 · 運用パターン — クラスター、モニタリング、デバッグ
ストリーミングジョブの運用は OLTP・OLAP と違う。24/7 で回り、state が積もり、一度間違えると backfill が悲惨。
基本ガイド。
- 分離されたクラスター / 分離されたジョブ: 一つの OOM が他に飛び火しないよう。
- チェックポイント頻度: 30s〜1m が一般的。短いと負荷、長いと復旧が遅い。
- State TTL 必須: そうしないと keyed state が無限累積。
- メトリクス: Prometheus + Grafana で Flink JobManager・TaskManager メトリクス。lag、checkpoint 時間、backpressure、state サイズ。
- アラート: コンシューマ lag、checkpoint 失敗、restart カウント、late events。
- Backfill 戦略: state-free ジョブは Kafka 最初から再処理。state-ful は savepoint 活用。
- Blue/green デプロイ: 新バージョンを別コンシューマグループで立ち上げ、結果比較後に cutover。
Flink-on-Kubernetes は標準になった。Flink Kubernetes Operator(Apache OSS)が安定し、Helm chart 一発で開始可能。
helm repo add flink-operator-repo https://downloads.apache.org/flink/flink-kubernetes-operator-1.10.0/
helm install flink-kubernetes-operator flink-operator-repo/flink-kubernetes-operator
FlinkDeployment CRD でジョブ定義。
apiVersion: flink.apache.org/v1beta1
kind: FlinkDeployment
metadata:
name: my-streaming-job
spec:
image: flink:2.0
flinkVersion: v2_0
taskManager:
replicas: 4
resource: { memory: "4096m", cpu: 2 }
job:
jarURI: s3://my-jobs/my-job.jar
parallelism: 8
upgradeMode: savepoint
25章 · コストモデル — ストリーム処理の本当の値段
ストリーム処理のコストは常時稼働から来る。バッチは終われば 0 だがストリーミングは 24/7。
コスト構成。
- コンピュート: TaskManager インスタンス。通常最大費目。
- 状態ストレージ: RocksDB ローカル SSD または S3(ForSt)。
- Kafka inter-AZ 転送: 上述の Kafka コスト。
- チェックポイント S3 PUT/GET。
- モニタリング・ログコスト(Datadog、NewRelic)。
コスト削減パターン。
- state TTL で RAM 削減。
- Disaggregated state(ForSt、RisingWave)で SSD 節約。
- オートスケーリング: Flink Adaptive Scheduler で負荷に応じて TM 数調整。
- Spot/Preemptible: stateless operator は spot OK。
- Confluent KIP-848 / Share Groups でコンシューマ効率化。
- WarpStream + Flink: state は ForSt、データは WarpStream → S3 コストのみ。
Confluent Cloud Flink は Compute Pool 単位で課金、未使用時は 0 にスケール(scale to zero)。小規模チームには合うが、hot ジョブのコストは一般的に OSS Flink + EKS より高い。
26章 · まとめ — 2026年のストリーム処理推奨
長い記事だった。最後に一行ガイド。
- Kafka 中心 + Java チーム + ストリーム処理開始: Kafka Streams + ksqlDB(小規模)または Flink SQL(中大規模)。
- 複雑な CEP / 大きな state / マルチソース: Apache Flink 2.0(DataStream + SQL)。
- アプリが Postgres でクエリ / Materialized View 必要: RisingWave 2.x(大規模)または Materialize(複雑 SQL)。
- Python ML 統合 / 小規模: Bytewax または Quix Streams。
- 運用したくない、GUI 必要: Decodable または Confluent Cloud Flink。
- 単純 ETL/変換(ウィンドウほぼ無し): Redpanda Connect (Benthos) または Pulsar Functions。
- CDC + ストリーミング統合: Estuary Flow または Debezium + Flink。
- Rust モノトーンシングルバイナリ好み: Arroyo。
2026年に最大のトレンドはストリーミングデータベースの台頭。RisingWave と Materialize が「ストリーム処理はデータエンジニアの領域」という通念を崩している。一行の CREATE MATERIALIZED VIEW でバックエンドエンジニアが直接リアルタイムビューを作る。Flink は依然として強力だが、**「Flink が必要か?」**を先に問う時代になった。
そしてもう一つ — 状態がクラウドストレージへ移動している。ForSt、RisingWave の S3 backed state、Arroyo の設計全てが同じ方向。broker が stateless に近づき、データは S3 に。これは Kafka で始まった disaggregation トレンドが stream processor まで来たもの。
長い記事の終わり。2026年のストリーム処理はもはや一つの正解がない。選択肢が増え、それゆえに選択の責任が大きくなった。どうか自分のワークロードに合った道具を選んでほしい。
参考資料
- Apache Flink 2.0 Release Notes
- Flink FLIP-435: Materialized Tables
- Flink ForSt (Disaggregated State)
- Apache Kafka Streams Documentation
- KIP-932: Queues for Kafka
- ksqlDB Documentation
- RisingWave Documentation
- Materialize Documentation
- Differential Dataflow
- Arroyo Streams
- Bytewax Documentation
- Apache Beam Documentation
- Apache Pulsar Functions
- Quix Streams
- Decodable Documentation
- Confluent Cloud Flink
- Aiven for Apache Flink
- Amazon MSF (Managed Service for Apache Flink)
- Estuary Flow
- Redpanda Connect (Benthos)
- Memphis.dev / Superstream
- Confluent Schema Registry
- Streaming Systems book by Tyler Akidau
- Mercari Engineering Blog
- Coupang Engineering Blog
- LINE Yahoo Engineering