通過Spark的UDAF看各類大數據組件
在IT界,每一項技術的興起往往是因爲這項技術解決了某項痛點。
- C語言作爲高級語言興起,很大程度是因爲降低了編程難度(對比彙編語言)。
- 數據庫的興起是因爲解決了重要數據的存儲問題。
- 以Hadoop爲首的大數據組件的興起,就是爲了應對爆炸增長的數據量。
大數據處理的原理
Hadoop是最先興起的大數據組件,它應對海量數據的方法核心就是:分佈式,高可用。翻譯成人話就是:團隊合作。一臺機器處理不了,我們就多臺機器一起處理嘛。一項任務做不完,就開公司找人一起做!
Hadoop之類的大數據組件核心思想都是靠多臺機器一起分工協作完成,但是機器的合作究竟要怎麼實現呢?有沒有什麼具體的例子可以闡述呢?我最近在編寫Spark的用戶自定義聚合函數(UDAF)時,發現它就是一個極好的例子!
Spark UDAF(用戶自定義聚合函數)
官網代碼:
(可只查看末尾的 update,merge,evaluate 方法)
object MyAverage extends UserDefinedAggregateFunction {
// 輸入數據
def inputSchema: StructType = StructType(StructField("inputColumn", LongType) :: Nil)
// 聚合時所用緩存器Buffer數據類型
def bufferSchema: StructType = {
StructType(StructField("sum", LongType) :: StructField("count", LongType) :: Nil)
}
// 回傳數據
def dataType: DataType = DoubleType
// Whether this function always returns the same output on the identical input
def deterministic: Boolean = true
// 初始化Buffer
def initialize(buffer: MutableAggregationBuffer): Unit = {
buffer(0) = 0L
buffer(1) = 0L
}
// 數據輸入時更新Buffer
def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
if (!input.isNullAt(0)) {
buffer(0) = buffer.getLong(0) + input.getLong(0)
buffer(1) = buffer.getLong(1) + 1
}
}
// 合併Buffer
def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
buffer1(0) = buffer1.getLong(0) + buffer2.getLong(0)
buffer1(1) = buffer1.getLong(1) + buffer2.getLong(1)
}
// 計算最終結果
def evaluate(buffer: Row): Double = buffer.getLong(0).toDouble / buffer.getLong(1)
}
計算邏輯類比人類團隊協作
- update方法
buffer處理輸入數據; ===> 每個單人處理部分工作 - merge方法
將多個buffer各自的計算結果合併; ===> 兩人之間工作合作 - evaluate方法
將所有buffer合成的數據最後算出結果; ===> 多人合作完成項目
另一個例子:Hadoop的MapReduce就是一個很好的例子;
- Map端將大任務拆解爲小任務;
- 小任務分解給各個partition(計算資源)計算;
- Reduce端將大家計算好的小任務合併,並算出最終結果;
一點感想
由此,我們可以很清楚的理解,Hadoop是靠多機器團隊協作達到處理海量數據的目的;Hive的出現是爲了降低MapReduce的上手難度,並提供分析大量數據的操作方法;Spark的快速計算同樣是靠多機器團隊協作,但對比MapReduce,Spark能利用內存計算,而不是隻依靠較慢的磁盤讀寫,所以速度更快。這就像是請了更專業,更強的員工一樣。
計算機技術在不斷更新迭代,但它們的原理往往都來自生活。如果我們能夠形象,深刻的理解一些技術的核心思想,那對我們快速學習新技術是十分有幫助的。
這是本人開發的一點小感想,如有哪裏說得不對或不合適,歡迎您留言告訴我。反饋也是提升寫作必不可少的部分。
如果覺得寫得多少有點東西,麻煩您點一點下方的贊哦!!謝謝