Avro技術應用_12. 將 Avro 數據加載到 Spark 中

這是一篇翻譯,原文來自:How to load some Avro data into Spark

首先,爲什麼使用 Avro ?

最基本的格式是 CSV ,其廉價並且不需要頂一個一個 schema 和數據關聯。

隨後流行起來的一個通用的格式是 XML,其有一個 schema 和 數據關聯,XML 廣泛的使用於 Web Services 和 SOA 架構中。不幸的是,其非常冗長,並且解析 XML 需要消耗內存。

另外一種格式是 JSON,其非常流行易於使用因爲它非常方便易於理解。

這些格式在 Big Data 環境中都是不可拆分的,這使得他們難於使用。在他們之上使用一個壓縮機制(Snappy,Gzip)並不能解決這個問題。

因此不同的數據格式出現了。Avro 作爲一種序列化平臺被廣泛使用,因爲它能跨語言,提供了一個小巧緊湊的快速的二進制格式,支持動態 schema 發現(通過它的泛型)和 schema 演變,並且是可壓縮和拆分的。它還提供了複雜的數據結構,例如嵌套類型。

例子

讓我們來看一個例子,創建一個 Avro schema 並生成一些數據。在一個真實案例的例子中,組織機構通常有一些更加普通的格式,例如 XML,的數據,並且他們需要通過一些工具例如 JAXB 將他們的數據轉換成 Avro。我們來使用這個例子,其中 twitter.avsc 如下:

{
   "type" : "record",
   "name" : "twitter_schema",
   "namespace" : "com.miguno.avro",
   "fields" : [
        {     "name" : "username",
               "type" : "string",
              "doc"  : "Name of the user account on Twitter.com"   },
         {
             "name" : "tweet",
             "type" : "string",
             "doc"  : "The content of the user's Twitter message"   },
         {
             "name" : "timestamp",
             "type" : "long",
             "doc"  : "Unix epoch time in seconds"   } 
    ],
   "doc:" : "A basic schema for storing Twitter messages" 
}

twitter.json 中有一些數據:

{"username":"miguno","tweet":"Rock: Nerf paper, scissors is fine.","timestamp": 1366150681 } 
{"username":"BlizzardCS","tweet":"Works as intended.  Terran is IMBA.","timestamp": 1366154481 }

我們將這些數據轉換成二進制的 Avro 格式:

$ java -jar ~/avro-tools-1.7.7.jar fromjson --schema-file twitter.avsc twitter.json > twitter.avro

然後,我們將 Avro 數據轉換爲 Java:

$ java -jar /app/avro/avro-tools-1.7.7.jar compile schema /app/avro/data/twitter.avsc /app/avro/data/

現在,我們編譯這些類並將其打包:

$ CLASSPATH=/app/avro/avro-1.7.7-javadoc.jar:/app/avro/avro-mapred-1.7.7-hadoop1.jar:/app/avro/avro-tools-1.7.7.jar
$ javac -classpath $CLASSPATH /app/avro/data/com/miguno/avro/twitter_schema.java
$ jar cvf Twitter.jar com/miguno/avro/*.class

我們啓動 Spark,並將上面創建的 Jar 和一些需要的庫(Hadoop 和 Avro)傳遞給 Spark 程序:

$ ./bin/spark-shell --jars /app/avro/avro-mapred-1.7.7-hadoop1.jar,/avro/avro-1.7.7.jar,/app/avro/data/Twitter.jar

在 REPL 中,我們獲取數據並創建一個 RDD:

scala>
import com.miguno.avro.twitter_schema
import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.specific.SpecificDatumReader;
import org.apache.avro.mapreduce.AvroKeyInputFormat
import org.apache.avro.mapred.AvroKey
import org.apache.hadoop.io.NullWritable
import org.apache.avro.mapred.AvroInputFormat
import org.apache.avro.mapred.AvroWrapper
import org.apache.avro.generic.GenericRecord
import org.apache.avro.mapred.{AvroInputFormat, AvroWrapper}
import org.apache.hadoop.io.NullWritable


val path = "/app/avro/data/twitter.avro"
val avroRDD = sc.hadoopFile[AvroWrapper[GenericRecord], NullWritable, AvroInputFormat[GenericRecord]](path)
avroRDD.map(l => new String(l._1.datum.get("username").toString() ) ).first

返回結果:

res2: String = miguno

一些注意事項:

翻譯結束。


接下來,我將上述過程在 CDH 5.3 集羣中測試一遍。

驗證

首先,在集羣一個節點創建 twitter.avsc 和 twitter.json 兩個文件。

然後,使用 avro-tools 將這些數據轉換成二進制的 Avro 格式:

$ java -jar /usr/lib/avro/avro-tools.jar fromjson --schema-file twitter.avsc twitter.json > twitter.avro

這時候會生成 avro 文件:

$ ll
總用量 12
-rw-r--r-- 1 root root 543  3月 25 15:13 twitter.avro
-rw-r--r-- 1 root root 590  3月 25 15:12 twitter.avsc
-rw-r--r-- 1 root root 191  3月 25 15:12 twitter.json

將 Avro 數據轉換爲 Java:

$ java -jar /usr/lib/avro/avro-tools.jar compile schema twitter.avsc .

這時候會生成 twitter_schema.java 文件:

$ tree
.
├── com
│   └── miguno
│       └── avro
│           └── twitter_schema.java
├── twitter.avro
├── twitter.avsc
└── twitter.json

這時候會生成一個 Twitter.jar 的 jar 包。

編譯這些類並將其打包:

$ CLASSPATH=/usr/lib/avro/avro-mapred-hadoop2.jar:/usr/lib/avro/avro-tools.jar
$ javac -classpath $CLASSPATH com/miguno/avro/twitter_schema.java
$ jar cvf Twitter.jar com/miguno/avro/*.class

在當前目錄,運行 spark-shell:

spark-shell --jars /usr/lib/avro/avro-mapred-hadoop2.jar,/usr/lib/avro/avro.jar,Twitter.jar

將 twitter.avro 上傳到 hdfs:

hadoop fs -put twitter.avro

在 REPL 中,我們創建一個 RDD 並查看結果是否和上面一致:

scala>
import com.miguno.avro.twitter_schema;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.DatumWriter;
import org.apache.avro.specific.SpecificDatumReader;
import org.apache.avro.mapreduce.AvroKeyInputFormat
import org.apache.avro.mapred.AvroKey
import org.apache.hadoop.io.NullWritable
import org.apache.avro.mapred.AvroInputFormat
import org.apache.avro.mapred.AvroWrapper
import org.apache.avro.generic.GenericRecord
import org.apache.avro.mapred.{AvroInputFormat, AvroWrapper}
import org.apache.hadoop.io.NullWritable


val path = "twitter.avro"
val avroRDD = sc.hadoopFile[AvroWrapper[GenericRecord], NullWritable, AvroInputFormat[GenericRecord]](path)
avroRDD.map(l => new String(l._1.datum.get("username").toString() ) ).first

更多的 Avro Tools 用法,可以參考 Avro 介紹

發佈了71 篇原創文章 · 獲贊 1 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章