Transcript

2 0 1 6 . 0 8

F r o m J a v a S t r e a m t o J a v a D a t a F r a m e

P o p c o r n y ( 陸 振 恩 )

Outline• 動機• 從 Java Stream 到 DataFrame 的歷程• Poppy 簡介 • Demo

動機• TenMax 是一個廣告平台• 廣告就是要看報表• 所有發生的 event 我們稱為 rawlog

• rawlog 每個小時產生一次 Aggregated Data

• 看報表時可以以選擇一個時間區間,根據某些維度 (dimensions) ,可以看出某些數值 (metrics)

• 這是常見的 OLAP技巧

Raw LogAggregated Data

(Cube)

BatchaggregateIngest

InteractiveQuery

如果是單純的 RDBMS

RDBMS(RawLog)

RDBMS(Cube)

BatchaggregateIngest

InteractiveQuery

RDBMS 的困境• 傳統的 RDBMS 不適合非常大量的 Log Ingestion

• 更適合的有– DFS: 但是 Append-Only 的環境比較適合– Cassandra/Hbase: 除了 Insert, 還可以 Row-based 的 update, delete, partition scan

DFS or Cassandra RDBMS

BatchaggregateIngest

InteractiveQuery

但是, Aggregation 就要自己來了

Aggregation 有哪些 Solution• Computation Engine

– Hadoop MapReduce

– Hive

– Spark SQL

– Impala

• 但是都有以下的缺點– 原本的設計都是針對 Cluster 環境所設計– Heavy weight

– 過多的 Dependency ( 如果要把 driver 包在自己的程式中 )

– 只對 HDFS-Compatible 的 data source 比較友善– Job 啟動速度– 如果要定義自己的 UDF / UDAF 會很複雜– 學習門檻– 維運門檻– …..

這些對大數據都是很好的 Solution ,但是對中數據呢 ?

中數據• 資料量

– 一天會新增 1G ~ 1T uncompressed data

• 假設– 一筆 record = 1K, 1T 資料 = 10 億筆資料– CPU 1 core 一秒可以處理 1 萬筆資料– 四核一天可以處理 34.56 億筆資料

• 其實一台機器綽綽有餘• 更何況雲端機器可以 Scale up ,到 16 核都不是問題• I/O 跟 Network throughput 漸漸不是瓶頸• 單機跑的 solution 可以減少很多的 overhead

• 單程序跑的 solution 也好寫好 debug

那就自己來寫 Aggregation 吧

Java8• 語言特色 Lambda

• 三神器– Stream

– Optional

– CompletableFuture

Java Stream• Functional Reactive Programming (FRP)

• Pipeline Style , Input 透過一站一站的 transformation 最後輸出到 Output

• Streaming 的特性,非常少的 Memory Footprint ,可以處理非常大量的資料。

forEach()map() filter() flapMap() peek()

那 Aggregation 呢 ?

先了解一下 SQL 吧

From RawLog

Where (DayRange)

GroupBy

sum(),sum(),sum()hour=?,dim1=?,dim2=?

val1, val2, val3

sum(),sum(),sum()hour=?,dim1=?,dim2=?

val1, val2, val3

sum(),sum(),sum()hour=?,dim1=?,dim2=?

val1, val2, val3

sum(),sum(),sum()hour=?,dim1=?,dim2=?

val1, val2, val3

sum(),sum(),sum()hour=?,dim1=?,dim2=?

val1, val2, val3

sum(),sum(),sum()hour=?,dim1=?,dim2=?

val1, val2, val3

Java Stream Aggregation

From

Where

GroupBy Aggregationcount(), sum()

然後 Mapper 是

然後 Reducer 是

Java Stream• 對於這種應用好像有點複雜• 不太好用的平行處理• java.util.stream.Collector 對於多 metrics 的 aggregation 很麻煩• 有些時候我們想要的是 Column Based 的操作,而不是單純的對一個 Type 操作

所以我們開發了 Poppy

http://tenmax.github.io/poppy/

Introduction to Poppy• Poppy 是一個 Java 的 DataFrame Library

• 什麼是 Data Frame?

– Column based (Schema)

– 可以做類似 RDBMS 的相關操作 select, from, where, group by, aggregation, order by

• Poppy 還有以下特色– Stream based ( 適合較大數據 )

– 支援 partition 以及平行計算– User Defined Function, User Defined Aggregation Function

– Lightweight

• 其實就是有 Schema 版本的 Java Stream

http://tenmax.github.io/poppy/

Poppy 大概長這樣

from

where

group by

aggregation

That’s All!!

Poppy

• Pipeline 分成三部分– Input

– Operations

– Output

http://tenmax.github.io/poppy/

OutputOperation Operation Operation OperationInput

Input• By Iterable

DataFrame.from(Class<T> clazz, java.util.Iterable... iterables)

• By DataSource

DataFrame.from(io.tenmax.DataSource dataSource)

• 其中 DataSource 的定義是

http://tenmax.github.io/poppy/

Output• iterator(), forEach()

• toList(),toMap(), print()

• DataFrame.to(DataSink dataSink)

• 其中 DataSink 的定義是

http://tenmax.github.io/poppy/

Operations• project()

• filter()

• Aggregation()

• groupby()

• Sort()

• distinct()

• peek()

• cache()

http://tenmax.github.io/poppy/

Projection (Select)

http://tenmax.github.io/poppy/

Filter (Where, Having)

http://tenmax.github.io/poppy/

Aggregation (Count, Sum, Avg, …)

http://tenmax.github.io/poppy/

Sort (Order by)

http://tenmax.github.io/poppy/

Distinct

http://tenmax.github.io/poppy/

Demo

http://tenmax.github.io/poppy/

User-Defined Function

http://tenmax.github.io/poppy/

• 使用 java.util.function,Function<T,R>

User-Defined Aggregation Function

http://tenmax.github.io/poppy/

• 使用 java.util.stream,Collector<T,A,R>

平行計算• Partition 是平行的基本單位• 一個 DataSource 可以提供多個 Partition

• 透過 dataFrame.parallel(n) 來決定平行的 thread 個數

http://tenmax.github.io/poppy/

Execution Context• 一個 Execution Context 代表的是一個 thread pool 。• 在其中可能有 n 個 threads ,以及 m 個 partitions

• 通常 m >= n ,每個 thread 在處理完一個 partition 之後,會去拉下一個還未處理的 partition

http://tenmax.github.io/poppy/

Execution Context• 每次呼叫 aggregation, sort, distinct 會產生一個新的 execution context 。

http://tenmax.github.io/poppy/

Demo

http://tenmax.github.io/poppy/

Conclusion• Java Stream 對於 Column-based 的需求不太容易處理。• 我們提供的 DataFrame Library – Poppy 提供了更簡單的方法來處理 Column-based 的資料。• 可以很輕易的平行化來處理大量的資料。• 但是又非常的 lightweight

http://tenmax.github.io/poppy/

Conclusion• Java Stream 對於 Column-based 的需求不太容易處理。• 我們提供的 DataFrame Library – Poppy 提供了更簡單的方法來處理 Column-based 的資料。• 可以很輕易的平行化來處理大量的資料。• 但是又非常的 lightweight

http://tenmax.github.io/poppy/

Reference• Project Site - http://tenmax.github.io/poppy/

• Poppy User Manual - http://tenmax.github.io/poppy/

• Poppy Javadoc - http://tenmax.github.io/poppy/docs/javadoc/index.html

• Java 多執行緒的基本知識 - https://www.gitbook.com/book/popcornylu/java_multithread/details

• pq - https://github.com/tenmax/pq

http://tenmax.github.io/poppy/

如果覺得不錯的話請幫我打一個星星

http://tenmax.github.io/poppy/

Thank you! Question?http://tenmax.github.io/poppy/


Top Related