Structured Streaming 介紹(一)

weixin_33670713發表於2017-08-01

最近看了下structured streaming 的基本用法,大部分雖然是翻譯官方文件,但是從翻譯中也可以加深理解。

基本介紹和程式設計模型

Spark2.2.0 在7月12號釋出,這個版本的Structured Streaming 拋掉了試驗的標籤,可以正式在生產環境使用。
Structured Streaming 是基於Spark SQL 引擎的流式計算引擎,將流式計算應用於DataFrame.隨著資料不斷地到達,Spark SQL引擎會以一種增量的方式來執行這些操作,並且持續更新計算結果。其基本概念就是將輸入資料流作為
“Input Table”,每次新收到的資料會成為該表新的一行。


1747200-1d99f1dd5778f2d4.png
Input Table

每次針對資料的查詢都會生成一個“Result Table”。每一次的
觸發間隔(比如說1s),Input Table 新增的一行,最終都會在Result Table 進行更新。當result table 更新的
時候,我們可能會將改變的資料寫入外部儲存。

1747200-656d8d6876b34568.png
Result Table

Input Source

File source - 以檔案流的形式讀取目錄中寫入的檔案。 支援的檔案格式為text,csv,json,parquet。 有關更多最新列表,可以看下DataStreamReader介面的文件,並支援各種檔案格式的選項。 請注意,檔案必須是被移動到目錄中的,比如用mv命令。
kafka source - 從kafka poll 資料,相容 kafka broker 0.10.0 或更高版本。更多詳情看
Kafka Integration Guide

Socket source (for testing )從socket 連線中讀取 UTF8 資料,僅用於測試,不提供容錯保證。

某些資料來源是不支援容錯的,因為它們不能保證在故障之後可以通過checkedpoint offsets 來重新消費資料。

Source Options Fault-tolerant Notes
File path:輸入路徑,適用所有格式 maxFilesPerTrigger:每次觸發時,最大新檔案數(預設:無最大) latestFirst:是否首先處理最新的檔案,當有大量積壓的檔案時,有用(預設值:false) fileNameOnly:是否僅根據檔名而不是完整路徑檢查新檔案(預設值:false)。將此設定為“true”,以下檔案將被視為相同的檔案,因為它們的檔名“dataset.txt”是相同的:· "file:///dataset.txt" "s3://a/dataset.txt" "s3n://a/b/dataset.txt" "s3a://a/b/c/dataset.txt" YES 支援glob路徑,但不支援多個逗號分隔的 paths/globs.
socket host port NO ------
kafka 參見Kafka Integration Guide YES ------

三種不同的輸出模式

Complete Mode - 更新後的整個Result Table將被寫入外部儲存。 由外部儲存決定如何處理整個表的寫入。
Append Mode - 在Result Table中,只有自上次觸發後新增到result table中的資料將被寫入外部儲存。 這僅適用於不期望更改結果表中現有行的查詢,也就是說,我們確定,result table中已有的資料是肯定不會被改變的,才使用這種模式。
Update Mode - 只有自上次觸發以後在Result Table中更新的資料(包括新增的和修改的)將被寫入外部儲存(可用於Spark 2.1.1)。 這與完全模式不同,因為此模式僅輸出自上次觸發以來更改的行。 如果查詢不包含聚合,它將等同於Append Mode。

簡單例子

object WordCount {
 def main(args: Array[String]): Unit = {
val spark = SparkSession.builder()
        .appName("WordCount")
        .master("local")
        .getOrCreate()
val lines = spark
        .readStream
        .format("socket")
        .option("host", "localhost")
        .option("port", 9999)
        .load()
import spark.implicits._
val words = lines.as[String].flatMap(_.split(" "))
val wordCount=  words .groupBy("value").count()
 //執行此程式碼後,流式計算將在後臺啟動。
 //qurey物件是該活動流查詢的控制程式碼
  //使用awaitTermination()等待查詢的終止.
val qurey = wordCount.writeStream
        .outputMode(OutputMode.Complete())
        .trigger(Trigger.ProcessingTime(2))
        .format("console")
        .start()
qurey.awaitTermination()
   }
 }

lines 為DataFrame是input table,這個表包含了一個名為"value"的列,現在還沒有開始收到任何資料,因為我們只是做了transformation操作。 接下來,我們使用.as [String]將DataFrame轉換為String資料集,通過flatMap操作將每一行分割成多個單詞。 最後,我們通過分組操作生成wordCounts DataFrame。通過start()方法開啟流計算。

流資料生成的DataFrame經查詢生成wordCounts與靜態DataFrame完全相同。 但是,當該查詢啟動時,Spark將連續檢查套接字連線中的新資料。 如果有新資料,Spark將執行一個“增量”查詢,將以前的執行計數與新資料相結合,以計算更新的計數,如下所示。


1747200-18c23f6ec960dd2b.png
Word Count Example

相關文章