SlideShare a Scribd company logo
2016年12月15日
1
ヤフー株式会社 データ&サイエンスソリューション統括本部
データプラットフォーム本部 開発1部 パイプライン
森谷 大輔
噛み砕いてKafka Streams
自己紹介
• 氏名
• 森谷 大輔 @kokumutyoukan
• 業務
• 次世代データパイプラインの開発
• Kafka, Storm,
Cassandra, Elasticsearch
• 好き
• 横浜ベイスターズ
• ハングリータイガー(の会会長)
2
今日のゴール
• おっ、調べてみるかなという気になってもらう
• Kafka Streamsを触った内容を噛み砕いて紹介
• 布教というわけではない
• 気になるところあれば遠慮なくツッコんでください
3
アジェンダ
• 概要
• Word Count
• Time, Window, Join
• つかってみた
• まとめ
4
アジェンダ
• 概要
• Word Count
• Time, Window, Join
• つかってみた
• まとめ
5
Kafka Streams is 何
• ストリーム処理のアプリケーションを書くためのライブラリ
• Apache Kafka に同梱されている
• 0.10.0 からアップデートの目玉として追加 (2016年5月)
6
群雄割拠勢
Confluentが開発・導入促進を
頑張っている
ストリーム処理アプリケーションをつくるには
• よく必要になる「難しい機能」
• パーティショニング・拡張性
• 故障してもうまいこと復旧する(ステート管理)
• 遅れてやってきたデータもうまいこと処理する(時間の扱い)
• 再処理
• ウィンドウ集計
• 方法①:素のKafka Java APIを使う
• 方法②:ストリーム処理フレームワークを使う
• 方法③:Kafka Streamsを使う
7
①:素の Kafka Java API を使う
• お手軽
• Java ライブラリなのでアプリケーションを書いて jar にかためて java コ
マンドで起動さえすれば良い
• デプロイがシンプル
• 覚えることはAPIの使い方だけ
• ただし「難しい機能」を自分で考えて実装しなければならない
8
Consumer<byte[], byte[]> consumer = new KafkaConsumer<>(props);
consumer.subscribe(topics);
②:ストリーム処理フレームワークを使う
• Stormなど群雄割拠勢
• 「難しい機能」を含めリッチな機能が使える
• ただしフレームワークの専用クラスタが必要
• フレームワークならではの構成、設定、書き方
• デプロイ複雑
• 覚えることが多い
9
③:Kafka Streamsを使う
• 「Kafka Streamsはフレームワークではなく、ライブラリ」
• 「難しい機能」も抽象化されている
• 大体のパターンのストリーム処理アプリケーションを書くには充分
• リアルタイム性
• Spark Streamingのようなマイクロバッチではなく、Stormのような逐次処理(at least once)
• レイテンシ要求が厳しい案件でもOK
10
・サーバを分散処理モードで動かすためにセッティングし、
・フレームワークのとりきめに従ったアプリケーションの実装をし、
・専用のデプロイツールでデプロイしてはじめて分散処理
・ライブラリをクラスパスに含めてjarにかためてjavaコマンドうてば動く
比較
11
方法
(難しい機能)
実装の簡単さ
学習
コスト
運用(デプロイ)
コスト
① 素のKafka
Java APIを使う ✕ ◯ ◯
② ストリーム処理
フレームワークを使う ◯ ✕ ✕
③ Kafka Streams
◯ △ ◯
※独断と偏見
※ストリーム処理フレームワークにしかない機能もある
アジェンダ
• 概要
• Word Count
• Time, Window, Join
• つかってみた
• まとめ
12
ことはじめ
13
• ビルド設定(maven)
• APIを選ぶ
• high-level DSL ←今回はこれ
• low-level API
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-streams</artifactId>
<version>0.10.0.1</version>
</dependency>
プログラム
14
@Test
public final void wordCount() {
KStreamBuilder builder = new KStreamBuilder();
KStream<String, String> queryStream
= builder.stream(stringSerde, stringSerde, “search-query-topic”); // 入力トピック名は複数指定可能
KStream<String, Long> wordCounts = queryStream
.flatMapValues(value -> Arrays.asList(value.split(“¥¥s+”))) // 空白区切り分割
.map((key, value) -> new KeyValue<>(value, value)) // key 毎カウント下準備
.countByKey(stringSerde, “Counts”) // KStream -> KTable
.toStream(); // KTable -> KStream
wordCounts.to(stringSerde, longSerde, “wordcount-output”); // sink トピックに結果を書く
KafkaStreams streams = new KafkaStreams(builder, props); // props は Kafka Streams の設定
streams.start(); // アプリケーション実行
}
入力・結果例
15
// 入力
producer.send(new ProducerRecord<>(“search-query-topic”, “ぬこ 飼い方”));
producer.send(new ProducerRecord<>(“search-query-topic”, “犬 飼い方”));
producer.send(new ProducerRecord<>(“search-query-topic”, “本当すこ ぬこ"));
consumer.subscribe(Arrays.asList("wordcount-output"));
while (true) {
ConsumerRecords<String, Long> records = consumer.poll(100);
for (ConsumerRecord<String, Long> record : records) {
System.out.println("record = " + record.key() + ", " + record.value());
}
}
// 出力
record = ぬこ, 1
record = 飼い方, 1
record = 犬, 1
record = 飼い方, 2
record = 本当すこ, 1
record = ぬこ, 2
アプリケーションの動作確認は
Kafka Unit Testを使うと便利
※Kafka 公式 FAQ 参照
KStream? KTable?
• KStream
• record streamを扱う場合はKStreamクラスを使う
• 自己完結のデータストリーム
• 例えばPVログ、サーバログ、ツイート
• KTable
• changelog streamを扱う場合はKTableクラスを使う
• 状態を持つ、keyで値が更新されるデータのストリーム
• 例えばこの単語が今までに何件出現したか、のようなデータ
• Stateとしてローカルに保持される
16
アジェンダ
• 概要
• Word Count
• Time, Window, Join
• つかってみた
• まとめ
17
Time
• ストリームであるイベントが流れてきた時、そのイベントのタイムスタンプとしてどんな情
報を使うべきか
• 例えばイベントがツイートだとして、一時間毎のツイート数を計算したいといった場合、な
んのタイムスタンプ毎に計算する?
1. ユーザがツイートした瞬間
2. ツイートをAPIからバックエンドサーバが受け取ってKafkaに投げた瞬間
3. Kafkaに入った瞬間
4. Kafka Streamsがそのイベントを処理した瞬間
18
Tweet!
Twitter
API
my BE
server
Kafka Streams
① ② ③ ④
Time
• ストリームであるイベントが流れてきた時、そのイベントのタイムスタンプとしてどんな情
報を使うべきか
• 例えばイベントがツイートだとして、一時間毎のツイート数を計算したいといった場合、な
んのタイムスタンプ毎に計算する?
1. ユーザがツイートした瞬間
2. ツイートをAPIからバックエンドサーバが受け取ってKafkaに投げた瞬間
3. Kafkaに入った瞬間
4. Kafka Streamsがそのイベントを処理した瞬間
• 多くは1だと思うが、アプリケーションの仕様によって異なる
• Kafka Streamsでは設定項目 timestamp.extractor でどれを選択するか簡単に決められ
る
19
Kafka Streams的分類
• event-time
• ログ内の独自タイムスタンプの場合
• 「ユーザがツイートした瞬間」
• Kafka messageに付与されているタイムスタンプを使う場合
• 「ツイートをAPIからバックエンドサーバが受け取ってKafkaに投げた瞬間」
• broker設定 log.message.timestamp.type=CreateTime (デフォルト)
• このタイムスタンプはKafka0.10からMessageに付与される
• 0.9以前のproducerから投げると -1
• ingestion-time
• 「Kafkaに入った瞬間」
• log.message.timestamp.type=LogAppendTime だった場合
• そのイベントがKafka Brokerに入ったときの時刻がmessageタイムスタンプに付与
• processing-time
• 「Kafka Streamsがそのイベントを処理した瞬間」
20
timestamp.extractor
21
Time分類 timestamp.extractor
event-time(独自) 自分で実装する
event-time(message) ConsumerRecordTimestampExtractor
ingestion-time ConsumerRecordTimestampExtractor
processing-time WallclockTimestampExtractor
import java.util.Properties;
import org.apache.kafka.streams.StreamsConfig;
Properties props = new Properties();
props.put(StreamsConfig.TIMESTAMP_EXTRACTOR_CLASS_CONFIG,
WallclockTimestampExtractor.class.getName());
設定例
独自クラス実装例
22
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.streams.processor.TimestampExtractor;
// TimestampExtractorインタフェースを実装する
public class MyEventTimeExtractor implements TimestampExtractor {
@Override public long extract(ConsumerRecord<Object, Object> record) {
// ログをパースしてtimestampを取り出す
Foo myPojo = (Foo) record.value();
if (myPojo != null) {
return myPojo.getTimestampInMillis();
} else {
// valueがnullだったらとりあえず現在時刻をいれておく
return System.currentTimeMillis();
}
}
}
http://docs.confluent.io/3.0.0/streams/developer-guide.html#timestamp-extractor (コメント以外引用)
Window
23
• Tumbling time window
• 5分毎のユーザ毎のPV数とか
• Hopping time window
• 1つのイベントが複数のウィンドウにまたがる
KStream<String, String> viewsByUser = ユーザIDがkeyのPVログStreamなど;
KTable<Windowed<String>, Long> userCounts =
viewsByUser.countByKey(TimeWindows.of(”WindowName", 5 * 60 * 1000L));
TimeWindows.of(”WindowName", 5 * 60 * 1000L).advanceBy(60 * 1000L);
Join
24
• ストリーム処理でよくやるストリームとテーブルのJoinができる
• KTableはローカルにあり、常に最新である
• メッセージ処理毎にネットワークを超えてKVSを叩く必要も、鮮度を諦めて定期的にRDBを
メモリにロードする必要もない
KStream<String, String> voteRegionStream = ...(“vote-topic”)
KTable<String, String> partyTable = ...("party-topic");
KStream<String, String> voteParty
= voteRegionStream.leftJoin(
partyTable, (region, party) -> region + ”," + party);
k: Hillary v: California k: candidate v: party
Hillary Democratic
Trump Republican
k: Hillary v: California, Democratic
アジェンダ
• 概要
• Word Count
• Time, Window, Join
• つかってみた
• まとめ
25
Kafka Streamsで開発してみた
• Kafkaクラスタから引いた全メッセージをグルーピング、ウィンドウ集計して指標をsinkに
書くシンプルなアプリ
• ローカルでテストは通った、本番デプロイいこう
• バグを踏む:Kafka-4160 (´・ω・`)
• Kafka Streamsのフォアグラウンドスレッドとバッググラウンド
ハートビートスレッドの間に単一のロックがある
• タスク生成中にハートビートをブロックするのでタスク生成が長い
とセッションタイムアウトを超える
• consumerがグループから追い出されて再度タスク生成を始める
• 永遠に繰り返してデッドロックみたくなる
• 入力パーティション数が少ないと問題にならないのだが
本番では1topicあたり最大60あったため本番で初めて発覚した
26
続き
• バグは Kafka 0.10.1.0 で解消されたよ!(今client, server共に 0.10.0.1)
• Kafka Streams をバージョンアップすれば解決しそう
• > Apps built with Kafka Streams 0.10.1 only work against Kafka clusters running
0.10.1+.
• 古いサーバに対しても互換性なんとかしたいとは書いてあった
• 0.10.0.1のKafkaにバグフィックスだけパッチ当ててアプリに入れるか・・・
• 対象コードが 0.10.1 で大きく変わってて厳しい
• やっぱりサーバあげよう ← イマココ
27
___________
/|:: ┌──────┐ ::|
/. |:: | Exception | ::| / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
|.... |:: | Use 0.10.1 !| ::| | マイナーバージョンアップなら…アレ?
|.... |:: | .| ::| \_ ______
|.... |:: └──────┘ ::| ∨
\_| ┌────┐ .| ∧∧
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ( _)
/ ̄ ̄ ̄ ̄ ̄旦 ̄(_, )
/ \
| ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|、_)
 ̄| ̄| ̄ ̄ ̄ ̄ ̄ ̄|
思ったこと
• 向くユースケースなら向く
• Kafka Streamsのコンセプトがわかってきてからシステム設計した方がいいかも
• 既にカッチリ決まった要件にKafka Streamsを合わせようとするとハックするはめになるかも
• ライブラリならアプリケーション開発を楽にしてくれなくちゃいけない
• Kafkaの素のハイレベルAPIがそもそもかなりちょうどいい抽象化
• Kafka Streams APIの利点が活かせるかどうか
• インターナルトピックをかなり大量に作ることを想定している(アプリのバージョンアップご
とにトピックは増える)
• 小さめのサービス専用クラスタとかならいいが、マルチテナント向けのクラスタだとちょっと気持ち悪
いかも
• 現在は1 Kafkaクラスタしか指定できないが将来的には複数可能になるかも
28
アジェンダ
• 概要
• Word Count
• Time, Window, Join
• つかってみた
• まとめ
29
まとめ
• Kafka Streamsはストリーム処理のアプリケーションを実装するためのライブ
ラリ
• シンプルながらストリーム処理でよく必要になる、自分で実装するには難し
い機能を実現する
• 時間軸に何を使うか開発者が選択できる
• Kafka Streamsが便利に使えるようにシステム設計をすると吉
30
Appendix
31
Kafka Streamsはどこで動くの?
32
• consumerアプリケーション
• 普通はKafkaクラスタの(物理的に)近くのアプリケーション専用サーバ上でJavaプロセスとして動
かすと思う
• ライブラリなので何でもできるが、Kafkaとしか接続しないように全体設計すると楽そう
Kafkaクラスタ
source topic
internal topic
sink topic
Kafka
Streams
Kafka
Connect 等
Kafka
Connect 等
Configuration
33
import java.util.Properties;
import org.apache.kafka.streams.StreamsConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ConsumerConfig;
Properties settings = new Properties();
settings.put(StreamsConfig.APPLICATION_ID_CONFIG, “my-app”); // StreamConfigのこの3つは必須
settings.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, ”localhost:9092");
settings.put(StreamsConfig.ZOOKEEPER_CONNECT_CONFIG, ”localhost:2181");
settings.put(ProducerConfig...., “”); // 必須でない
settings.put(ConsumerConfig...., “”); // 必須でない
application.id アプリケーション認識名. consumer group名やinternal topic名等に利用される.
bootstrap.servers 接続するKafkaクラスタのhost/portペアのリスト.
zookeeper.connect 接続するZooKeeperのコネクション文字列(host:port/chroot).
num.stream.threads ストリーム処理のために使うスレッド数.
replication.factor internal topicを作るときのレプリケーションファクタ
state.dir State Storeのディレクトリパス
timestamp.extractor 後述
フォールトトレラント
• 故障時にStateを復旧させるため、Kafkaクラスタにchangelog topicという内部topicが作ら
れる
34
Node
Task
source part-1
changelog part-1
Node
Task
source part-0
changelog part-0
フォールトトレラント
• 故障時にStateを復旧させるため、Kafkaクラスタにchangelog topicという内部topicが作ら
れる
35
Node
Task
source part-1
changelog part-1
Node
Tasksource part-0
changelog part-0
Task
changelog topic(おまけ)
• topicはKafka Streamsアプリケーションの実行時に自動で作成される
• 手動でtopicを作るときと同じような感じで、Kafka設定
auto.create.topics.enable=falseでも作成される
• topic設定はcompact
• 同じkeyで頻繁にvalueが変わるはずだから
• タスク数分パーティションが作られる
36
プログラム(full)
37
@Test
public final void wordCount() {
final Serde<String> stringSerde = Serdes.String(); // Serde is Serializer/Deserializerの略、Kafka共通のクラス
final Serde<Long> longSerde = Serdes.Long(); // 基本的なビルトインをSerdesから呼べる、もちろん自作可能
KStreamBuilder builder = new KStreamBuilder();
// 入力名からKStreamを作る. 1: key Serde, 2: value Serde, 3: 入力トピック名(複数指定可能)
KStream<String, String> queryStream = builder.stream(stringSerde, stringSerde, “search-query-topic”);
KStream<String, Long> wordCounts = queryStream
// valueに対して空白区切りで文字列を分割して次に送る処理
.flatMapValues(value -> Arrays.asList(value.split(“¥¥s+”)))
// key毎カウントしたいからkeyにvalueを入れる
.map((key, value) -> new KeyValue<>(value, value))
.countByKey(stringSerde, “Counts”) // KStream -> KTable、第二引数はKTable名
.toStream(); // KTable -> KStream
wordCounts.to(stringSerde, longSerde, “wordcount-output”); // sinkトピックに結果を書く
KafkaStreams streams = new KafkaStreams(builder, props); // propsはKafka StreamsやClientの設定Properties
streams.start(); // アプリケーション実行
}
比較(full)
38
方法
(難しい機能)
実装の簡単さ
学習
コスト
運用(デプロイ)
コスト
実績
ドキュメント
充実度
① 素のKafka
Java APIを使う ✕ ◯ ◯ ◯ ◯
② ストリーム処理
フレームワークを使う ◯ ✕ ✕ △
(差異が大きい)
△?
③ Kafka Streams
◯ △ ◯ ✕ △
※独断と偏見

More Related Content

PDF
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
PDF
Apache Kafka 0.11 の Exactly Once Semantics
PPT
Cassandraのしくみ データの読み書き編
PDF
Apache Kafkaって本当に大丈夫?~故障検証のオーバービューと興味深い挙動の紹介~
PPTX
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
PDF
MQTTとAMQPと.NET
PDF
Java Clientで入門する Apache Kafka #jjug_ccc #ccc_e2
PPTX
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)
At least onceってぶっちゃけ問題の先送りだったよね #kafkajp
Apache Kafka 0.11 の Exactly Once Semantics
Cassandraのしくみ データの読み書き編
Apache Kafkaって本当に大丈夫?~故障検証のオーバービューと興味深い挙動の紹介~
え、まって。その並列分散処理、Kafkaのしくみでもできるの? Apache Kafkaの機能を利用した大規模ストリームデータの並列分散処理
MQTTとAMQPと.NET
Java Clientで入門する Apache Kafka #jjug_ccc #ccc_e2
Kubernetesでの性能解析 ~なんとなく遅いからの脱却~(Kubernetes Meetup Tokyo #33 発表資料)

What's hot (20)

PDF
超実践 Cloud Spanner 設計講座
PPTX
本当は恐ろしい分散システムの話
PDF
並行処理初心者のためのAkka入門
PDF
ストリーム処理を支えるキューイングシステムの選び方
PPTX
Redisの特徴と活用方法について
PPTX
イベント・ソーシングを知る
PPTX
今こそ知りたいSpring Web(Spring Fest 2020講演資料)
PDF
YugabyteDBを使ってみよう(NewSQL/分散SQLデータベースよろず勉強会 #1 発表資料)
PDF
マイクロサービス 4つの分割アプローチ
PDF
KafkaとAWS Kinesisの比較
PDF
分散DB Apache Kuduのアーキテクチャ DBの性能と一貫性を両立させる仕組み 「HybridTime」とは
PDF
BuildKitの概要と最近の機能
PDF
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
PDF
分散トレーシング技術について(Open tracingやjaeger)
PDF
普通の人でもわかる Paxos
PDF
わかる!metadata.managedFields / Kubernetes Meetup Tokyo 48
PPTX
モノリスからマイクロサービスへの移行 ~ストラングラーパターンの検証~(Spring Fest 2020講演資料)
PDF
AWS Black Belt Online Seminar 2018 Amazon DynamoDB Advanced Design Pattern
PPTX
初心者向けMongoDBのキホン!
超実践 Cloud Spanner 設計講座
本当は恐ろしい分散システムの話
並行処理初心者のためのAkka入門
ストリーム処理を支えるキューイングシステムの選び方
Redisの特徴と活用方法について
イベント・ソーシングを知る
今こそ知りたいSpring Web(Spring Fest 2020講演資料)
YugabyteDBを使ってみよう(NewSQL/分散SQLデータベースよろず勉強会 #1 発表資料)
マイクロサービス 4つの分割アプローチ
KafkaとAWS Kinesisの比較
分散DB Apache Kuduのアーキテクチャ DBの性能と一貫性を両立させる仕組み 「HybridTime」とは
BuildKitの概要と最近の機能
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
分散トレーシング技術について(Open tracingやjaeger)
普通の人でもわかる Paxos
わかる!metadata.managedFields / Kubernetes Meetup Tokyo 48
モノリスからマイクロサービスへの移行 ~ストラングラーパターンの検証~(Spring Fest 2020講演資料)
AWS Black Belt Online Seminar 2018 Amazon DynamoDB Advanced Design Pattern
初心者向けMongoDBのキホン!
Ad

Viewers also liked (20)

PDF
Kafka通常オペレーションで遭遇する問題集 #kafkajp
PDF
ストリーム処理プラットフォームにおけるKafka導入事例 #kafkajp
PPTX
Kafkaを活用するためのストリーム処理の基本
PDF
Kafkaを使った マイクロサービス基盤 part2 +運用して起きたトラブル集
PDF
Queryable State for Kafka Streamsを使ってみた
PDF
Processing Kafka Topics for Monitoring with Prometheus
PDF
Kafka 0.10.0 アップデート、プロダクション100ノードでやってみた #yjdsnight
PDF
Awsでつくるapache kafkaといろんな悩み
PPTX
Elasticsearch 5.2とJava Clientで戯れる #elasticsearchjp
PDF
Yahoo! JAPAN MeetUp #8 (インフラ技術カンファレンス)セッション②
PDF
Yahoo! JAPANが持つデータ分析ソリューションの紹介 #yjdsnight
PDF
Kafkaによるリアルタイム処理
PDF
第2回 NIPS+読み会・関西 発表資料 山本
PDF
Prestoクエリログの保存/分析機能の構築 #yjdsnight
PDF
Presto in Yahoo! JAPAN #yjdsnight
PDF
Yahoo! JAPANのサービス開発を10倍早くした社内PaaS構築の今とこれから
PDF
Storm の新機能について @HSCR #hadoopreading
PDF
Presto - Hadoop Conference Japan 2014
PDF
グロースハック なぜ我々は無意味な施策を打ってしまうのか
PDF
市場で勝ち続けるための品質とテストの技術①
Kafka通常オペレーションで遭遇する問題集 #kafkajp
ストリーム処理プラットフォームにおけるKafka導入事例 #kafkajp
Kafkaを活用するためのストリーム処理の基本
Kafkaを使った マイクロサービス基盤 part2 +運用して起きたトラブル集
Queryable State for Kafka Streamsを使ってみた
Processing Kafka Topics for Monitoring with Prometheus
Kafka 0.10.0 アップデート、プロダクション100ノードでやってみた #yjdsnight
Awsでつくるapache kafkaといろんな悩み
Elasticsearch 5.2とJava Clientで戯れる #elasticsearchjp
Yahoo! JAPAN MeetUp #8 (インフラ技術カンファレンス)セッション②
Yahoo! JAPANが持つデータ分析ソリューションの紹介 #yjdsnight
Kafkaによるリアルタイム処理
第2回 NIPS+読み会・関西 発表資料 山本
Prestoクエリログの保存/分析機能の構築 #yjdsnight
Presto in Yahoo! JAPAN #yjdsnight
Yahoo! JAPANのサービス開発を10倍早くした社内PaaS構築の今とこれから
Storm の新機能について @HSCR #hadoopreading
Presto - Hadoop Conference Japan 2014
グロースハック なぜ我々は無意味な施策を打ってしまうのか
市場で勝ち続けるための品質とテストの技術①
Ad

Similar to 噛み砕いてKafka Streams #kafkajp (20)

PDF
Kafka Summit NYCに見るストリーミングデータETLの話 #streamdatajp
PDF
Reactive Kafka with Akka Streams
PDF
20191120 AWS Black Belt Online Seminar Amazon Managed Streaming for Apache Ka...
PDF
Fast Data を扱うためのデザインパターン
PDF
Akka stream
PDF
ESP32ではじめようIoTハンズオン-サーバーサイド.pdf
PDF
Akka Stream x Kinesis at Shinjuku reactive meetup vol2
PPTX
Connect S3 with Kafka using Akka Streams
PDF
Kafka Streamsによるスケーラブルで非環境依存なストリーム/バッチ処理アーキテクチャ
PDF
Akka stream
PDF
Reactor Netty & Apache Kafka Stack #jsug
PDF
スキーマつきストリーム データ処理基盤、 Confluent Platformとは?
PPTX
Spark Structured Streaming with Kafka
PDF
Dataworks Summit 2017 SanJose StreamProcessing - Hadoop Source Code Reading #...
PPTX
Spark Structured StreamingでKafkaクラスタのデータをお手軽活用
PDF
Apache Kafka on Herokuを活用したイベント駆動アーキテクチャの設計と実装
PDF
IoT時代におけるストリームデータ処理と急成長の Apache Flink
PDF
ストリーム処理はデータを失うから怖い?それ、何とかできますよ! 〜Apahe Kafkaを用いたストリーム処理における送達保証〜 (Open Source...
PDF
最近のストリーム処理事情振り返り
Kafka Summit NYCに見るストリーミングデータETLの話 #streamdatajp
Reactive Kafka with Akka Streams
20191120 AWS Black Belt Online Seminar Amazon Managed Streaming for Apache Ka...
Fast Data を扱うためのデザインパターン
Akka stream
ESP32ではじめようIoTハンズオン-サーバーサイド.pdf
Akka Stream x Kinesis at Shinjuku reactive meetup vol2
Connect S3 with Kafka using Akka Streams
Kafka Streamsによるスケーラブルで非環境依存なストリーム/バッチ処理アーキテクチャ
Akka stream
Reactor Netty & Apache Kafka Stack #jsug
スキーマつきストリーム データ処理基盤、 Confluent Platformとは?
Spark Structured Streaming with Kafka
Dataworks Summit 2017 SanJose StreamProcessing - Hadoop Source Code Reading #...
Spark Structured StreamingでKafkaクラスタのデータをお手軽活用
Apache Kafka on Herokuを活用したイベント駆動アーキテクチャの設計と実装
IoT時代におけるストリームデータ処理と急成長の Apache Flink
ストリーム処理はデータを失うから怖い?それ、何とかできますよ! 〜Apahe Kafkaを用いたストリーム処理における送達保証〜 (Open Source...
最近のストリーム処理事情振り返り

More from Yahoo!デベロッパーネットワーク (20)

PDF
ゼロから始める転移学習
PDF
継続的なモデルモニタリングを実現するKubernetes Operator
PDF
ヤフーでは開発迅速性と品質のバランスをどう取ってるか
PDF
オンプレML基盤on Kubernetes パネルディスカッション
PDF
オンプレML基盤on Kubernetes 〜Yahoo! JAPAN AIPF〜
PDF
Persistent-memory-native Database High-availability Feature
PDF
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
PDF
eコマースと実店舗の相互利益を目指したデザイン #yjtc
PDF
ヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtc
PDF
Yahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtc
PDF
ビッグデータから人々のムードを捉える #yjtc
PDF
サイエンス領域におけるMLOpsの取り組み #yjtc
PDF
ヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtc
PDF
Yahoo! JAPAN Tech Conference 2022 Day2 Keynote #yjtc
PDF
新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc
PDF
PC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtc
PDF
モブデザインによる多職種チームのコミュニケーション改善 #yjtc
PDF
「新しいおうち探し」のためのAIアシスト検索 #yjtc
PDF
ユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtc
ゼロから始める転移学習
継続的なモデルモニタリングを実現するKubernetes Operator
ヤフーでは開発迅速性と品質のバランスをどう取ってるか
オンプレML基盤on Kubernetes パネルディスカッション
オンプレML基盤on Kubernetes 〜Yahoo! JAPAN AIPF〜
Persistent-memory-native Database High-availability Feature
データの価値を最大化させるためのデザイン~データビジュアライゼーションの方法~ #devsumi 17-E-2
eコマースと実店舗の相互利益を目指したデザイン #yjtc
ヤフーを支えるセキュリティ ~サイバー攻撃を防ぐエンジニアの仕事とは~ #yjtc
Yahoo! JAPANのIaaSを支えるKubernetesクラスタ、アップデート自動化への挑戦 #yjtc
ビッグデータから人々のムードを捉える #yjtc
サイエンス領域におけるMLOpsの取り組み #yjtc
ヤフーのAIプラットフォーム紹介 ~AIテックカンパニーを支えるデータ基盤~ #yjtc
Yahoo! JAPAN Tech Conference 2022 Day2 Keynote #yjtc
新技術を使った次世代の商品の見せ方 ~ヤフオク!のマルチビュー機能~ #yjtc
PC版Yahoo!メールリニューアル ~サービスのUI/UX統合と改善プロセス~ #yjtc
モブデザインによる多職種チームのコミュニケーション改善 #yjtc
「新しいおうち探し」のためのAIアシスト検索 #yjtc
ユーザーの地域を考慮した検索入力補助機能の改善の試み #yjtc

噛み砕いてKafka Streams #kafkajp

  • 2. 自己紹介 • 氏名 • 森谷 大輔 @kokumutyoukan • 業務 • 次世代データパイプラインの開発 • Kafka, Storm, Cassandra, Elasticsearch • 好き • 横浜ベイスターズ • ハングリータイガー(の会会長) 2
  • 3. 今日のゴール • おっ、調べてみるかなという気になってもらう • Kafka Streamsを触った内容を噛み砕いて紹介 • 布教というわけではない • 気になるところあれば遠慮なくツッコんでください 3
  • 4. アジェンダ • 概要 • Word Count • Time, Window, Join • つかってみた • まとめ 4
  • 5. アジェンダ • 概要 • Word Count • Time, Window, Join • つかってみた • まとめ 5
  • 6. Kafka Streams is 何 • ストリーム処理のアプリケーションを書くためのライブラリ • Apache Kafka に同梱されている • 0.10.0 からアップデートの目玉として追加 (2016年5月) 6 群雄割拠勢 Confluentが開発・導入促進を 頑張っている
  • 7. ストリーム処理アプリケーションをつくるには • よく必要になる「難しい機能」 • パーティショニング・拡張性 • 故障してもうまいこと復旧する(ステート管理) • 遅れてやってきたデータもうまいこと処理する(時間の扱い) • 再処理 • ウィンドウ集計 • 方法①:素のKafka Java APIを使う • 方法②:ストリーム処理フレームワークを使う • 方法③:Kafka Streamsを使う 7
  • 8. ①:素の Kafka Java API を使う • お手軽 • Java ライブラリなのでアプリケーションを書いて jar にかためて java コ マンドで起動さえすれば良い • デプロイがシンプル • 覚えることはAPIの使い方だけ • ただし「難しい機能」を自分で考えて実装しなければならない 8 Consumer<byte[], byte[]> consumer = new KafkaConsumer<>(props); consumer.subscribe(topics);
  • 9. ②:ストリーム処理フレームワークを使う • Stormなど群雄割拠勢 • 「難しい機能」を含めリッチな機能が使える • ただしフレームワークの専用クラスタが必要 • フレームワークならではの構成、設定、書き方 • デプロイ複雑 • 覚えることが多い 9
  • 10. ③:Kafka Streamsを使う • 「Kafka Streamsはフレームワークではなく、ライブラリ」 • 「難しい機能」も抽象化されている • 大体のパターンのストリーム処理アプリケーションを書くには充分 • リアルタイム性 • Spark Streamingのようなマイクロバッチではなく、Stormのような逐次処理(at least once) • レイテンシ要求が厳しい案件でもOK 10 ・サーバを分散処理モードで動かすためにセッティングし、 ・フレームワークのとりきめに従ったアプリケーションの実装をし、 ・専用のデプロイツールでデプロイしてはじめて分散処理 ・ライブラリをクラスパスに含めてjarにかためてjavaコマンドうてば動く
  • 11. 比較 11 方法 (難しい機能) 実装の簡単さ 学習 コスト 運用(デプロイ) コスト ① 素のKafka Java APIを使う ✕ ◯ ◯ ② ストリーム処理 フレームワークを使う ◯ ✕ ✕ ③ Kafka Streams ◯ △ ◯ ※独断と偏見 ※ストリーム処理フレームワークにしかない機能もある
  • 12. アジェンダ • 概要 • Word Count • Time, Window, Join • つかってみた • まとめ 12
  • 13. ことはじめ 13 • ビルド設定(maven) • APIを選ぶ • high-level DSL ←今回はこれ • low-level API <dependency> <groupId>org.apache.kafka</groupId> <artifactId>kafka-streams</artifactId> <version>0.10.0.1</version> </dependency>
  • 14. プログラム 14 @Test public final void wordCount() { KStreamBuilder builder = new KStreamBuilder(); KStream<String, String> queryStream = builder.stream(stringSerde, stringSerde, “search-query-topic”); // 入力トピック名は複数指定可能 KStream<String, Long> wordCounts = queryStream .flatMapValues(value -> Arrays.asList(value.split(“¥¥s+”))) // 空白区切り分割 .map((key, value) -> new KeyValue<>(value, value)) // key 毎カウント下準備 .countByKey(stringSerde, “Counts”) // KStream -> KTable .toStream(); // KTable -> KStream wordCounts.to(stringSerde, longSerde, “wordcount-output”); // sink トピックに結果を書く KafkaStreams streams = new KafkaStreams(builder, props); // props は Kafka Streams の設定 streams.start(); // アプリケーション実行 }
  • 15. 入力・結果例 15 // 入力 producer.send(new ProducerRecord<>(“search-query-topic”, “ぬこ 飼い方”)); producer.send(new ProducerRecord<>(“search-query-topic”, “犬 飼い方”)); producer.send(new ProducerRecord<>(“search-query-topic”, “本当すこ ぬこ")); consumer.subscribe(Arrays.asList("wordcount-output")); while (true) { ConsumerRecords<String, Long> records = consumer.poll(100); for (ConsumerRecord<String, Long> record : records) { System.out.println("record = " + record.key() + ", " + record.value()); } } // 出力 record = ぬこ, 1 record = 飼い方, 1 record = 犬, 1 record = 飼い方, 2 record = 本当すこ, 1 record = ぬこ, 2 アプリケーションの動作確認は Kafka Unit Testを使うと便利 ※Kafka 公式 FAQ 参照
  • 16. KStream? KTable? • KStream • record streamを扱う場合はKStreamクラスを使う • 自己完結のデータストリーム • 例えばPVログ、サーバログ、ツイート • KTable • changelog streamを扱う場合はKTableクラスを使う • 状態を持つ、keyで値が更新されるデータのストリーム • 例えばこの単語が今までに何件出現したか、のようなデータ • Stateとしてローカルに保持される 16
  • 17. アジェンダ • 概要 • Word Count • Time, Window, Join • つかってみた • まとめ 17
  • 18. Time • ストリームであるイベントが流れてきた時、そのイベントのタイムスタンプとしてどんな情 報を使うべきか • 例えばイベントがツイートだとして、一時間毎のツイート数を計算したいといった場合、な んのタイムスタンプ毎に計算する? 1. ユーザがツイートした瞬間 2. ツイートをAPIからバックエンドサーバが受け取ってKafkaに投げた瞬間 3. Kafkaに入った瞬間 4. Kafka Streamsがそのイベントを処理した瞬間 18 Tweet! Twitter API my BE server Kafka Streams ① ② ③ ④
  • 19. Time • ストリームであるイベントが流れてきた時、そのイベントのタイムスタンプとしてどんな情 報を使うべきか • 例えばイベントがツイートだとして、一時間毎のツイート数を計算したいといった場合、な んのタイムスタンプ毎に計算する? 1. ユーザがツイートした瞬間 2. ツイートをAPIからバックエンドサーバが受け取ってKafkaに投げた瞬間 3. Kafkaに入った瞬間 4. Kafka Streamsがそのイベントを処理した瞬間 • 多くは1だと思うが、アプリケーションの仕様によって異なる • Kafka Streamsでは設定項目 timestamp.extractor でどれを選択するか簡単に決められ る 19
  • 20. Kafka Streams的分類 • event-time • ログ内の独自タイムスタンプの場合 • 「ユーザがツイートした瞬間」 • Kafka messageに付与されているタイムスタンプを使う場合 • 「ツイートをAPIからバックエンドサーバが受け取ってKafkaに投げた瞬間」 • broker設定 log.message.timestamp.type=CreateTime (デフォルト) • このタイムスタンプはKafka0.10からMessageに付与される • 0.9以前のproducerから投げると -1 • ingestion-time • 「Kafkaに入った瞬間」 • log.message.timestamp.type=LogAppendTime だった場合 • そのイベントがKafka Brokerに入ったときの時刻がmessageタイムスタンプに付与 • processing-time • 「Kafka Streamsがそのイベントを処理した瞬間」 20
  • 21. timestamp.extractor 21 Time分類 timestamp.extractor event-time(独自) 自分で実装する event-time(message) ConsumerRecordTimestampExtractor ingestion-time ConsumerRecordTimestampExtractor processing-time WallclockTimestampExtractor import java.util.Properties; import org.apache.kafka.streams.StreamsConfig; Properties props = new Properties(); props.put(StreamsConfig.TIMESTAMP_EXTRACTOR_CLASS_CONFIG, WallclockTimestampExtractor.class.getName()); 設定例
  • 22. 独自クラス実装例 22 import org.apache.kafka.clients.consumer.ConsumerRecord; import org.apache.kafka.streams.processor.TimestampExtractor; // TimestampExtractorインタフェースを実装する public class MyEventTimeExtractor implements TimestampExtractor { @Override public long extract(ConsumerRecord<Object, Object> record) { // ログをパースしてtimestampを取り出す Foo myPojo = (Foo) record.value(); if (myPojo != null) { return myPojo.getTimestampInMillis(); } else { // valueがnullだったらとりあえず現在時刻をいれておく return System.currentTimeMillis(); } } } http://docs.confluent.io/3.0.0/streams/developer-guide.html#timestamp-extractor (コメント以外引用)
  • 23. Window 23 • Tumbling time window • 5分毎のユーザ毎のPV数とか • Hopping time window • 1つのイベントが複数のウィンドウにまたがる KStream<String, String> viewsByUser = ユーザIDがkeyのPVログStreamなど; KTable<Windowed<String>, Long> userCounts = viewsByUser.countByKey(TimeWindows.of(”WindowName", 5 * 60 * 1000L)); TimeWindows.of(”WindowName", 5 * 60 * 1000L).advanceBy(60 * 1000L);
  • 24. Join 24 • ストリーム処理でよくやるストリームとテーブルのJoinができる • KTableはローカルにあり、常に最新である • メッセージ処理毎にネットワークを超えてKVSを叩く必要も、鮮度を諦めて定期的にRDBを メモリにロードする必要もない KStream<String, String> voteRegionStream = ...(“vote-topic”) KTable<String, String> partyTable = ...("party-topic"); KStream<String, String> voteParty = voteRegionStream.leftJoin( partyTable, (region, party) -> region + ”," + party); k: Hillary v: California k: candidate v: party Hillary Democratic Trump Republican k: Hillary v: California, Democratic
  • 25. アジェンダ • 概要 • Word Count • Time, Window, Join • つかってみた • まとめ 25
  • 26. Kafka Streamsで開発してみた • Kafkaクラスタから引いた全メッセージをグルーピング、ウィンドウ集計して指標をsinkに 書くシンプルなアプリ • ローカルでテストは通った、本番デプロイいこう • バグを踏む:Kafka-4160 (´・ω・`) • Kafka Streamsのフォアグラウンドスレッドとバッググラウンド ハートビートスレッドの間に単一のロックがある • タスク生成中にハートビートをブロックするのでタスク生成が長い とセッションタイムアウトを超える • consumerがグループから追い出されて再度タスク生成を始める • 永遠に繰り返してデッドロックみたくなる • 入力パーティション数が少ないと問題にならないのだが 本番では1topicあたり最大60あったため本番で初めて発覚した 26
  • 27. 続き • バグは Kafka 0.10.1.0 で解消されたよ!(今client, server共に 0.10.0.1) • Kafka Streams をバージョンアップすれば解決しそう • > Apps built with Kafka Streams 0.10.1 only work against Kafka clusters running 0.10.1+. • 古いサーバに対しても互換性なんとかしたいとは書いてあった • 0.10.0.1のKafkaにバグフィックスだけパッチ当ててアプリに入れるか・・・ • 対象コードが 0.10.1 で大きく変わってて厳しい • やっぱりサーバあげよう ← イマココ 27 ___________ /|:: ┌──────┐ ::| /. |:: | Exception | ::| / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ |.... |:: | Use 0.10.1 !| ::| | マイナーバージョンアップなら…アレ? |.... |:: | .| ::| \_ ______ |.... |:: └──────┘ ::| ∨ \_| ┌────┐ .| ∧∧  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ( _) / ̄ ̄ ̄ ̄ ̄旦 ̄(_, ) / \ | ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄|、_)  ̄| ̄| ̄ ̄ ̄ ̄ ̄ ̄|
  • 28. 思ったこと • 向くユースケースなら向く • Kafka Streamsのコンセプトがわかってきてからシステム設計した方がいいかも • 既にカッチリ決まった要件にKafka Streamsを合わせようとするとハックするはめになるかも • ライブラリならアプリケーション開発を楽にしてくれなくちゃいけない • Kafkaの素のハイレベルAPIがそもそもかなりちょうどいい抽象化 • Kafka Streams APIの利点が活かせるかどうか • インターナルトピックをかなり大量に作ることを想定している(アプリのバージョンアップご とにトピックは増える) • 小さめのサービス専用クラスタとかならいいが、マルチテナント向けのクラスタだとちょっと気持ち悪 いかも • 現在は1 Kafkaクラスタしか指定できないが将来的には複数可能になるかも 28
  • 29. アジェンダ • 概要 • Word Count • Time, Window, Join • つかってみた • まとめ 29
  • 30. まとめ • Kafka Streamsはストリーム処理のアプリケーションを実装するためのライブ ラリ • シンプルながらストリーム処理でよく必要になる、自分で実装するには難し い機能を実現する • 時間軸に何を使うか開発者が選択できる • Kafka Streamsが便利に使えるようにシステム設計をすると吉 30
  • 32. Kafka Streamsはどこで動くの? 32 • consumerアプリケーション • 普通はKafkaクラスタの(物理的に)近くのアプリケーション専用サーバ上でJavaプロセスとして動 かすと思う • ライブラリなので何でもできるが、Kafkaとしか接続しないように全体設計すると楽そう Kafkaクラスタ source topic internal topic sink topic Kafka Streams Kafka Connect 等 Kafka Connect 等
  • 33. Configuration 33 import java.util.Properties; import org.apache.kafka.streams.StreamsConfig; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ConsumerConfig; Properties settings = new Properties(); settings.put(StreamsConfig.APPLICATION_ID_CONFIG, “my-app”); // StreamConfigのこの3つは必須 settings.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, ”localhost:9092"); settings.put(StreamsConfig.ZOOKEEPER_CONNECT_CONFIG, ”localhost:2181"); settings.put(ProducerConfig...., “”); // 必須でない settings.put(ConsumerConfig...., “”); // 必須でない application.id アプリケーション認識名. consumer group名やinternal topic名等に利用される. bootstrap.servers 接続するKafkaクラスタのhost/portペアのリスト. zookeeper.connect 接続するZooKeeperのコネクション文字列(host:port/chroot). num.stream.threads ストリーム処理のために使うスレッド数. replication.factor internal topicを作るときのレプリケーションファクタ state.dir State Storeのディレクトリパス timestamp.extractor 後述
  • 36. changelog topic(おまけ) • topicはKafka Streamsアプリケーションの実行時に自動で作成される • 手動でtopicを作るときと同じような感じで、Kafka設定 auto.create.topics.enable=falseでも作成される • topic設定はcompact • 同じkeyで頻繁にvalueが変わるはずだから • タスク数分パーティションが作られる 36
  • 37. プログラム(full) 37 @Test public final void wordCount() { final Serde<String> stringSerde = Serdes.String(); // Serde is Serializer/Deserializerの略、Kafka共通のクラス final Serde<Long> longSerde = Serdes.Long(); // 基本的なビルトインをSerdesから呼べる、もちろん自作可能 KStreamBuilder builder = new KStreamBuilder(); // 入力名からKStreamを作る. 1: key Serde, 2: value Serde, 3: 入力トピック名(複数指定可能) KStream<String, String> queryStream = builder.stream(stringSerde, stringSerde, “search-query-topic”); KStream<String, Long> wordCounts = queryStream // valueに対して空白区切りで文字列を分割して次に送る処理 .flatMapValues(value -> Arrays.asList(value.split(“¥¥s+”))) // key毎カウントしたいからkeyにvalueを入れる .map((key, value) -> new KeyValue<>(value, value)) .countByKey(stringSerde, “Counts”) // KStream -> KTable、第二引数はKTable名 .toStream(); // KTable -> KStream wordCounts.to(stringSerde, longSerde, “wordcount-output”); // sinkトピックに結果を書く KafkaStreams streams = new KafkaStreams(builder, props); // propsはKafka StreamsやClientの設定Properties streams.start(); // アプリケーション実行 }
  • 38. 比較(full) 38 方法 (難しい機能) 実装の簡単さ 学習 コスト 運用(デプロイ) コスト 実績 ドキュメント 充実度 ① 素のKafka Java APIを使う ✕ ◯ ◯ ◯ ◯ ② ストリーム処理 フレームワークを使う ◯ ✕ ✕ △ (差異が大きい) △? ③ Kafka Streams ◯ △ ◯ ✕ △ ※独断と偏見