Upgrade to Pro — share decks privately, control downloads, hide ads and more …

KafkaとksqlDBと Streaming DB - Commit Log Streamを捌くテクノロジー

hashi
March 25, 2022

KafkaとksqlDBと Streaming DB - Commit Log Streamを捌くテクノロジー

Cloud Native Database Meetup #4 登壇資料

ksqlDBはKafkaを利用する事を前提としたストリーム処理エンジンです。 『DB』という名前が付いてはいますが、DBでありながらストリーム処理エンジンでもある少し変わった個性を持つ技術です。Kafkaエコシステムの中でKafka Streamsと共に育った技術ですが、ストリーム処理の枠を超えてDBとしての道を歩み始めています。

KafkaとKafka Streamsと強いつながりを持つksqlDBは、その特性を理解することで長所を生かした活用が可能です。

本セッションではksqlDBの概要、Kafka StreamsとksqlDBの関わりと、合わせてksqlDBの仕組みについてもご紹介いたします。

hashi

March 25, 2022
Tweet

More Decks by hashi

Other Decks in Technology

Transcript

  1. Cloud Native Database Meetup #4 ksqlDB and Streaming DB Shinichi

    Hashitani, Solutions Engineer, Mar. 2022. #CloudNativeDB
  2. @ShinHashitani | developer.confluent.io Kafka Keeps Data Consistent customer login: abc

    order confirmed: #001 order updated: #002 customer login: efg order canceled: #003 Append-Only Immutable 1 2 3 4 5 6 8 7 10 9 11 12 1 2 3 4 5 6 8 7 Old New
  3. @ShinHashitani | developer.confluent.io Kafka is a Durable Storage Broker 1

    Broker 2 Broker 3 Broker 4 Topic1 partition1 Topic1 partition2 Topic1 partition3 Topic1 partition4 Topic1 partition1 Topic1 partition1 Topic1 partition2 Topic1 partition2 Topic1 partition3 Topic1 partition3 Topic1 partition4 Topic1 partition4 Concurrent Access Data Replication
  4. @ShinHashitani | developer.confluent.io Connecting to Kafka - Data In/Out DB

    CONNECTOR CONNECTOR APP APP DB STREAM PROCESSING CONNECTOR APP DB
  5. @ShinHashitani | developer.confluent.io Stream Processing - Handling Data DB CONNECTOR

    CONNECTOR APP APP DB STREAM PROCESSING CONNECTOR APP DB
  6. @ShinHashitani | developer.confluent.io ksqlDB Abstraction DB APP APP DB PULL

    PUSH CONNECTORS STREAM PROCESSING MATERIALIZED VIEWS ksqlDB APP
  7. @ShinHashitani | developer.confluent.io Event and State - Pull Query and

    Push Query Seven Eleven payment: 500 JPY CREATE STREAM payments AS SELECT Account_id, store, amount FROM transactions EMIT CHANGES; CREATE TABLE payment_sum AS SELECT account_id, SUM (amount) FROM transactions GROUP BY account_id TUMBLING WINDOW (1 DAY) EMIT CHANGES; Yoshinoya payment: 800 JPY AEON payment: 2,400 JPY hashi: 3700 JPY PULL hashi: Seven Eleven, 500 JPY hashi: Yoshinoya, 800 JPY hashi: AEON, 2400 JPY PUSH hashi: 500 JPY hashi: 1300 JPY hashi: 3700 JPY PUSH
  8. @yourtwitterhandle | developer.confluent.io Easily Build Real-Time Apps Joins Aggregates Push

    & Pull Queries Filters User-Defined Functions Connectors Compute Storage ksqlDB Kafka CREATE TABLE activePromotions AS SELECT rideId, qualifyPromotion(distanceToDst) AS promotion FROM locations GROUP BY rideId EMIT CHANGES 複雑なリアルタイム処理アプリを 数行のSQLで表現 ksqlDB at a glance ksqlDB is a database for building real-time applications that leverage stream processing
  9. @ShinHashitani | developer.confluent.io Kafka Streams / ksqlDB - Abstraction Layers

    ksqlDB Kafka Streams Kafka Connect Producer Consumer Producer/Consumer、Kafka Streams、ksqlDBは独立した技 術ではなく同じスタックの異な る抽象化レイヤーを構成。 Kafka Streamsは Publisher/Consumerを利用し、 ksqlDBは内部でKafka Streams プロセスを実行している。
  10. @ShinHashitani | developer.confluent.io Kafka Streams and ksqlDB in Code ConsumerRecords<String,

    String> records = consumer.poll(100); Map<String, Integer> counts = new DefaultMap<String, Integer>(); for (ConsumerRecord<String, Integer> record : records) { String key = record.key(); int c = counts.get(key) c += record.value() counts.put(key, c) } for (Map.Entry<String, Integer> entry : counts.entrySet()) { int stateCount; int attempts; while (attempts++ < MAX_RETRIES) { try { stateCount = stateStore.getValue(entry.getKey()) stateStore.setValue(entry.getKey(), entry.getValue() + stateCount) break; } catch (StateStoreException e) { RetryUtils.backoff(attempts); } } } builder.stream("input-stream", Consumed.with(Serdes.String(), Serdes.String())) .groupBy((key, value) -> value) .count() .toStream() .to("counts", Produced.with(Serdes.String(), Serdes.Long())); SELECT x, count(*) FROM stream GROUP BY x EMIT CHANGES; Consumer Kafka Streams ksqlDB
  11. @ShinHashitani | developer.confluent.io Tools for Stream Processing ksqlDB Kafka Streams

    Producer Consumer • Stateless / Stateful • Java or pseudo-SQL • Stateless • Many Languages Kafka StreamがTopologyと ステート管理の機能を提供。 この為集約(SUM、AVG) 等の処理が可能であり、提供 言語がJavaのみとなる。 ksqlDBは擬似SQLでの利用 となるが、内部的にはKafka Stream処理に変換される為 中身はJava。
  12. @ShinHashitani | developer.confluent.io Kafka Streams - Topology and State Store

    Kafka Streams内で処理フローを管理。 状態は内部のDB (!) で管理。 (RocksDB)
  13. @ShinHashitani | developer.confluent.io Kafka Streams - Middleware in Library Karka

    StreamsはJavaライブラリ。一般的には専 用のランタイム構成が必要なストリーム処理をア プリ内で完結。 • StreamもしくはTableとしてデータを抽象化。 • Partition毎に処理。処理を分けるのではなく 対象データセットを分ける事で並列処理。 • Topology内を流れるのは常に1イベント。 Karka Stream Appは「分散処理オーケストレー ション」が可能なJava App。
  14. @ShinHashitani | developer.confluent.io ksqlDB Runtime ksqlDBは単体のJavaアプリとして稼働。 これらはKafka Brokerを経由して各々が 1つのクラスタであると認識して稼働す る。(セルフ

    オーケストレーション) • それぞれが1つのKafka Streamsアプ リケーションを内包。 • Kafka Streamsも別のIDでグループと して認識される。 • Kafka StreamsもConsumer API経由 でKafkaと通信 - 全て同一の Consumer Groupとして認識される。 ksql.service.id application.id group.id JVM ksqlDB Server Kafka Streams App Engine API Consumer API JVM ksqlDB Server Kafka Streams App Engine API Consumer API JVM ksqlDB Server Kafka Streams App Engine API Consumer API
  15. @ShinHashitani | developer.confluent.io SQL Engine DDLはKSQL内のmetastore (in-memory) に格納。 parse -

    ANTLRを利用してSQL構文をストリーム処理 構成に分割し論理ツリー (AST - Abstract Syntax Tree) に変換。 logical plan - ASTから実際のストリーム処理順序に 再構成 physical plan - 必要に応じてKStream、KTableを生 成。logical planで作成した順序通りにKafka Streams のトポロジーを構成。 SQL Engine Kafka Streams SQL parse logical plan physical plan
  16. @ShinHashitani | developer.confluent.io Task Deployment ksqlDBの処理はKafka Streams内ではTaskと呼ばれ、 それぞれ個別のThreadとして実行される。 • 同一Kafka

    Streams内に複数Threadが立ち上がる。 • Thread (ThreadLocal) はJVM内の論理的スレッド であり制御はJVMが行う。 (CPUの物理的なスレッ ドとは異なる) • State Store (RocksDB) はTask毎に占有される。(物 理的に異なるストア) • State StoreはRocksDB-less (インメモリ) を利用す る事も可能。但しリバランスに弱い。 Kafka Streams JVM Task Thread Thread Task Kafka Streams JVM Task Thread Thread Task
  17. @ShinHashitani | developer.confluent.io State Store and Changelog State Store •

    State StoreはRocksDB (LSM Tree) に格納。Kafka Streamsが実行するランタイムのディスクに保存。 (デ フォルトは/tmp/kafka-streams配下) • State Storeがchangelogに書き込み。changelogは State Store再構築用。 • changelogのオフセットも合わせて管理。 • Byte保存、Byteレプリケーション。 changelog Topic • State Storeと紐付く内部Topicが自動的に生成される。 • リバランス、障害等の理由でState Storeの再構築が必 要な場合この内部Topicから作成される。 • Compacted Topicで構成。 Kafka Streams changelog topic A topic B
  18. @ShinHashitani | developer.confluent.io JOIN Table/Stream共にPartitionに分割されている 為、JOINする為には該当KeyのEventが同じ Partition#に存在する必要がある。 • 物理的な (Broker)

    ではなく論理的な (Topic) 場所が同じ。同じTaskからアクセ ス。 • 同じKeyである: ◦ 同じPartitioningポリシー ◦ 同じPartition数 ◦ 同じKey GROUP BYや結合では内部で自動的にRe-Keyさ れる。処理としては重め。 • Internal Topicの生成 • Re-Key Kafka Streams Task Task Partition 0 Partition 1 Partition 0 Partition 1
  19. @ShinHashitani | developer.confluent.io Stand-by Replica and Interactive Query State StoreはTopologyからのみアクセス可だが、Read

    Only前提で 外部からのアクセスが可能 • get() range() all() approximateNumEntries() • Stand-by Replicaを指定したフェッチが可能。 Task内のState Store (Local)だけでなく、他のTaskのState Store (Remote)への参照が可能 • Kafka Streams内に実装。RPCかRESTで他のState Storeを参照 して代理でフェッチ。 • queryMetadataForKey() もしくは allMetadataForStore() Kafka Streams Kafka Streams Read Only Read Only
  20. @ShinHashitani | developer.confluent.io ksqlDB Server Materialized View Materialized ViewはTableの一種 •

    Pull Queryが可能なのはMaterialized Viewのみ。 • CREATE TABLEで作成したTableはクエリ不可 (単純な スキーマ定義) • 作成時にCTAS (CREATE TABLE AS) もしくは CST (CREATE SOURCE TABLE) いずれかの構文が必要。 Pull Kafka Streams Push
  21. @ShinHashitani | developer.confluent.io ksqlDB Server Pull Query and Push Query

    Pull Query • Key指定 <<< Range指定 • No Table Scan Yet (WHERE句必須) • Key指定以外の場合は複数のState Store結果の集約処 理が裏で走る。 • クエリ内で集約関数の利用不可。 Push Query • CTAS/CST定義時にEMIT CHANGES句を追加。 いずれもver. 0.22にてやや大きめなエンハンスメントが 追加され、今後も継続的に改善が見込まれる領域。 Pull Kafka Streams Push
  22. @ShinHashitani | developer.confluent.io Pattern 1 : ダッシュボードへの速報 Insurance DB INSERT

    INTO app_pipeline SELECT COUNT(*) FROM proposal prop INNER JOIN application app ON prop.plan_id = app.plan_id WHERE app.status IS NOT ‘pending’ GROUP BY prop.id WINDOW TUMBLING (SIZE 1 hour) EMIT CHANGES; Sales Dashboard proposal application KSQL app_pipeline KSQL hourly_close INSERT INTO hourly_close SELECT SUM(amount) COUNT(*) FROM application GROUP BY id WHERE app.status IS ‘signed’ WINDOW TUMBLING (SIZE 1 hour) EMIT CHANGES; app_pipeline hourly_close stream table process 各販売チャネルは速報や時間帯毎の細かな データを集計したいが、設計/申込データ は夜間バッチによる一括計上。既存アプリ への機能追加はコスト的に非現実的。 • DBの更新情報をCDCでキャプチャし ストリーム化 - アプリ/DBへの影響を 排除。 • 設計/申込データ更新時にイベント発 火 - 1時間Windowで区切った速報値 をKTableに常時更新。 • セールスダッシュボード等からはマテ リアライズされた速報値に対して Selectクエリを発行。
  23. @ShinHashitani | developer.confluent.io Pattern 2 : 決済の不正検知 transaction KSQL Detect

    fishy_account Store CREATE STREAM fishy_account AS SELECT account.id, COUNT(*) FROM transaction trans INNER JOIN account ON trans.account_id = account.id GROUP BY account.id HAVING COUNT(*) >= 3 WINDOW TUMBLING (SIZE 30 MINUTES) EMIT CHANGES; Customer Portal account KSQL SUSPEND CREATE STREAM suspended AS SELECT transaction.id account.id, transaction.amount FROM fishy_account INNER JOIN transaction ON bad_trans.account_id = transaction.account.id EMIT CHANGES; Admin Customer Portal suspended stream table process さらに複雑な検知ルール - アカウントの更新が30分 以内にあり、かつ3回以上決済手続きがあるアカウ ントを検知。 • accountデータは更新した場合のみ発生。クエ リはINNER JOINである為account更新がない 限り検出されない。 • 判定されたアカウントを所有するお客様には即 座に追知。 • 該当するaccount idをストリーム化。同様に対 象アカウントのトランザクションのみを抽出。 • 管理では既に決済済みトランザクションの後処 理、アカウント再開手続き等を引き続き実施。
  24. @ShinHashitani | developer.confluent.io Pattern 3: SIEM - インフラログ活用の最適化 KSQL Filter

    device_logs KSQL FIrewall KSQL DNS KSQL Auth firewall dns auth KSQL De-noise firewall_clean login Devices SIEM Admin KSQL User Map access_auth Audit Store Long-Term Store Auth CREATE STREAM device_logs AS SELECT event_id, event_type, EXPRODE (event) timestamp, .... FROM all_logs WHERE event_type = ‘firewall’ OR event_type = ‘dns’ OR event_type = ‘auth’ EMIT CHANGES; CREATE STREAM auth AS SELECT event, event_type, timestamp, .... FROM device_logs WHERE event_type = ‘firewall’ EMIT CHANGES; CREATE STREAM dns AS SELECT event, event_type, timestamp, .... FROM device_logs WHERE event_type = ‘firewall’ EMIT CHANGES; CREATE STREAM firewall AS SELECT event_type, port, message, timestamp, .... FROM device_logs WHERE event_type = ‘firewall’ EMIT CHANGES; CREATE STREAM access_auth AS SELECT auth.auth_id, auth.auth_type, auth.timestamp, login.authorized_by login.timestamp, .... FROM auth OUTER_JOIN login ON auth.login_id = login.login_id EMIT CHANGES; all_logs stream table process SIEMの保全コスト削減 • システム/保全サービスの多対多 の接続性をConfluentを経由する 多対一対多の構成に変更。 • フィルタリング、マッピング、カ ラムドロップ、ラベリング等を Confluentで実施。 • データ(ログ)の保全は安価なオ ブジェクトストレージで実施。保 全サービスにおけるデータ削減。
  25. @ShinHashitani | developer.confluent.io Pattern 4 : ゲーム - リーダーボード stream

    table process CREATE TABLE LOSSES_PER_USER AS SELECT USER, COUNT(USER) AS TOTAL_LOSSES FROM USER_LOSSES GROUP BY USER; CREATE TABLE STATS_PER_USER AS SELECT UG.USER AS USER, MAX(UG.GAME->SCORE) AS HIGHEST_SCORE, MAX(UG.GAME->LEVEL) AS HIGHEST_LEVEL, MAX(CASE WHEN LPU.TOTAL_LOSSES IS NULL THEN CAST(0 AS BIGINT) ELSE LPU.TOTAL_LOSSES END) AS TOTAL_LOSSES FROM USER_GAME UG LEFT JOIN LOSSES_PER_USER LPU ON UG.USER = LPU.USER GROUP BY UG.USER; Player user_game user_losses KSQL Loss per User losses_per_user KSQL User Stats stats_per_user Leaderboard CREATE TABLE SUMMARY_STATS AS SELECT 'SUMMARY_KEY' AS SUMMARY_KEY, MAX(GAME->SCORE) AS HIGHEST_SCORE_VALUE, COLLECT_SET(USER) AS USERS_SET_VALUE FROM USER_GAME GROUP BY 'SUMMARY_KEY'; KSQL Summary Stats summary_stats
  26. @ShinHashitani | developer.confluent.io ksqlDB Abstraction - How It Is Perceived

    DB APP APP DB PULL PUSH CONNECTORS STREAM PROCESSING MATERIALIZED VIEWS ksqlDB APP
  27. @ShinHashitani | developer.confluent.io Kafka and ksqlDB - Database Inside Out

    fsync buffer load 1 2 3 4 5 6 8 7 10 9 11 12 1 2 3 4 5 6 8 7 Tables Materialized Views Query Engine Storage