Skip to content

필사 모드: ストリーム処理 2026 完全ガイド - Kafka Streams・Flink SQL・RisingWave・Materialize・Arroyo・ksqlDB・Bytewax・Decodable 徹底解説

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

プロローグ — 「リアルタイムでお願い」という一言の重さ

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 の後継として吸収されつつある。

それでも**選択の出発点はパラダイム**だ。次の意思決定ツリーを推奨する。

1. **「Kafka トピック間のデータ変換と集計だけ必要」** → Kafka Streams(Java/Scala)または ksqlDB(SQL)。

2. **「複雑なウィンドウ/ジョイン/CEP、非 Kafka ソース、ペタバイト級」** → Flink(SQL または DataStream API)。

3. **「アプリは Postgres でクエリしたい、Materialized View が自動更新されてほしい」** → RisingWave または Materialize。

4. **「Python データサイエンティストが直接使えなければ」** → Bytewax または Quix。

5. **「運用したくない、SaaS で済ませたい」** → Decodable、Confluent Cloud Flink、Aiven Flink。

6. **「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** アルゴリズムに基づく分散スナップショット。

1. JobManager が定期的に checkpoint barrier を source に注入。

2. Barrier がデータと共に dataflow を下流に流れる。

3. 各 operator が barrier を受け取ると自身の状態をスナップショット。

4. Sink が barrier を受け取ると sink 固有の commit(Kafka は transactional producer commit)。

5. 全 operator が ack するとチェックポイント完了。

障害時。

1. 最後の成功した checkpoint から全 operator の状態を復元。

2. Source は当該 checkpoint の offset から再読込。

3. 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 モデルをそのままストリームに適用できる。

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**。

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 リスク。

対応パターン。

1. **自然な backpressure(pull ベース)**: Flink/Kafka Streams は基本 pull ベースで backpressure を自然に伝播。

2. **バッファリング**: Kafka 自体が巨大バッファ。データロスなくコンシューマがキャッチアップする時間を与える。

3. **Async I/O**: Flink AsyncFunction で外部呼び出しを並列化。

4. **Drop / Sample**: 本当に追いつかないなら一部イベントを drop(モニタリング・メトリクスは OK、決済は NG)。

5. **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 が悲惨。

基本ガイド。

1. **分離されたクラスター / 分離されたジョブ**: 一つの OOM が他に飛び火しないよう。

2. **チェックポイント頻度**: 30s〜1m が一般的。短いと負荷、長いと復旧が遅い。

3. **State TTL 必須**: そうしないと keyed state が無限累積。

4. **メトリクス**: Prometheus + Grafana で Flink JobManager・TaskManager メトリクス。lag、checkpoint 時間、backpressure、state サイズ。

5. **アラート**: コンシューマ lag、checkpoint 失敗、restart カウント、late events。

6. **Backfill 戦略**: state-free ジョブは Kafka 最初から再処理。state-ful は savepoint 活用。

7. **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)。

コスト削減パターン。

1. **state TTL で RAM 削減**。

2. **Disaggregated state(ForSt、RisingWave)で SSD 節約**。

3. **オートスケーリング**: Flink Adaptive Scheduler で負荷に応じて TM 数調整。

4. **Spot/Preemptible**: stateless operator は spot OK。

5. **Confluent KIP-848 / Share Groups でコンシューマ効率化**。

6. **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](https://nightlies.apache.org/flink/flink-docs-release-2.0/)

- [Flink FLIP-435: Materialized Tables](https://cwiki.apache.org/confluence/display/FLINK/FLIP-435%3A+Introduce+a+New+Dynamic+Table+for+Simplifying+Data+Pipelines)

- [Flink ForSt (Disaggregated State)](https://github.com/ververica/ForSt)

- [Apache Kafka Streams Documentation](https://kafka.apache.org/40/documentation/streams/)

- [KIP-932: Queues for Kafka](https://cwiki.apache.org/confluence/display/KAFKA/KIP-932%3A+Queues+for+Kafka)

- [ksqlDB Documentation](https://docs.ksqldb.io/)

- [RisingWave Documentation](https://docs.risingwave.com/)

- [Materialize Documentation](https://materialize.com/docs/)

- [Differential Dataflow](https://github.com/TimelyDataflow/differential-dataflow)

- [Arroyo Streams](https://www.arroyo.dev/)

- [Bytewax Documentation](https://bytewax.io/docs)

- [Apache Beam Documentation](https://beam.apache.org/documentation/)

- [Apache Pulsar Functions](https://pulsar.apache.org/docs/functions-overview/)

- [Quix Streams](https://quix.io/docs/quix-streams/)

- [Decodable Documentation](https://docs.decodable.co/)

- [Confluent Cloud Flink](https://docs.confluent.io/cloud/current/flink/overview.html)

- [Aiven for Apache Flink](https://aiven.io/flink)

- [Amazon MSF (Managed Service for Apache Flink)](https://docs.aws.amazon.com/managed-flink/)

- [Estuary Flow](https://docs.estuary.dev/)

- [Redpanda Connect (Benthos)](https://docs.redpanda.com/redpanda-connect/)

- [Memphis.dev / Superstream](https://memphis.dev/)

- [Confluent Schema Registry](https://docs.confluent.io/platform/current/schema-registry/index.html)

- [Streaming Systems book by Tyler Akidau](https://www.oreilly.com/library/view/streaming-systems/9781491983867/)

- [Mercari Engineering Blog](https://engineering.mercari.com/en/blog/)

- [Coupang Engineering Blog](https://medium.com/coupang-engineering)

- [LINE Yahoo Engineering](https://techblog.lycorp.co.jp/en/)

현재 단락 (1/610)

2026年のあるフィンテックの会議室。

작성 글자: 0원문 글자: 27,903작성 단락: 0/610