本系列共兩篇文章,主要探討如何將Ignite和Spark進行集成。
下面簡要地回顧一下在第一篇文章中所談到的內容。
Ignite是一個分佈式的內存數據庫、緩存和處理平臺,爲事務型、分析型和流式負載而設計,在保證擴展性的前提下提供了內存級的性能。
Spark是一個流式數據和計算引擎,通常從HDFS或者其他存儲中獲取數據,一直以來,他都傾向於OLAP型業務,並且聚焦於MapReduce類型負載。
因此,這兩種技術是可以互補的。
將Ignite與Spark整合
整合這兩種技術會爲Spark用戶帶來若干明顯的好處:
- 通過避免大量的數據移動,獲得真正可擴展的內存級性能;
- 提高RDD、DataFrame和SQL的性能;
- 在Spark作業之間更方便地共享狀態和數據。
下圖中顯示瞭如何整合這兩種技術,並且標註了顯著的優勢:
在第一篇文章中,主要聚焦於IgniteRDD,而本文會聚焦於IgniteDataFrames。
IgniteDataframes
Spark的DataFrame API爲描述數據引入了模式的概念,Spark通過表格的形式進行模式的管理和數據的組織。
DataFrame是一個組織爲命名列形式的分佈式數據集,從概念上講,DataFrame等同於關係數據庫中的表,並允許Spark使用Catalyst查詢優化器來生成高效的查詢執行計劃。而RDD只是跨集羣節點分區化的元素集合。
Ignite擴展了DataFrames,簡化了開發,改進了將Ignite作爲Spark的內存存儲時的數據訪問時間,好處包括:
- 通過Ignite讀寫DataFrames時,可以在Spark作業之間共享數據和狀態;
- 通過優化Spark的查詢執行計劃加快SparkSQL查詢,這些主要是通過IgniteSQL引擎的高級索引以及避免了Ignite和Spark之間的網絡數據移動實現的。
IgniteDataframes示例
下面通過一些代碼以及搭建幾個小程序的方式,瞭解Ignite DataFrames如何使用,如果想實際運行這些代碼,可以從GitHub上下載。
一共會寫兩個Java的小應用,然後在IDE中運行,還會在這些Java應用中執行一些SQL。
一個Java應用會從JSON文件中讀取一些數據,然後創建一個存儲於Ignite的DataFrame,這個JSON文件Ignite的發行版中已經提供,另一個Java應用會從Ignite的DataFrame中讀取數據然後使用SQL進行查詢。
下面是寫應用的代碼:
public class DFWriter {
private static final String CONFIG = "config/example-ignite.xml";
public static void main(String args[]) {
Ignite ignite = Ignition.start(CONFIG);
SparkSession spark = SparkSession
.builder()
.appName("DFWriter")
.master("local")
.config("spark.executor.instances", "2")
.getOrCreate();
Logger.getRootLogger().setLevel(Level.OFF);
Logger.getLogger("org.apache.ignite").setLevel(Level.OFF);
Dataset<Row> peopleDF = spark.read().json(
resolveIgnitePath("resources/people.json").getAbsolutePath());
System.out.println("JSON file contents:");
peopleDF.show();
System.out.println("Writing DataFrame to Ignite.");
peopleDF.write()
.format(IgniteDataFrameSettings.FORMAT_IGNITE())
.option(IgniteDataFrameSettings.OPTION_CONFIG_FILE(), CONFIG)
.option(IgniteDataFrameSettings.OPTION_TABLE(), "people")
.option(IgniteDataFrameSettings.OPTION_CREATE_TABLE_PRIMARY_KEY_FIELDS(), "id")
.option(IgniteDataFrameSettings.OPTION_CREATE_TABLE_PARAMETERS(), "template=replicated")
.save();
System.out.println("Done!");
Ignition.stop(false);
}
}
在DFWriter
中,首先創建了SparkSession
,它包含了應用名,之後會使用spark.read().json()
讀取JSON文件並且輸出文件內容,下一步是將數據寫入Ignite存儲。下面是DFReader
的代碼:
public class DFReader {
private static final String CONFIG = "config/example-ignite.xml";
public static void main(String args[]) {
Ignite ignite = Ignition.start(CONFIG);
SparkSession spark = SparkSession
.builder()
.appName("DFReader")
.master("local")
.config("spark.executor.instances", "2")
.getOrCreate();
Logger.getRootLogger().setLevel(Level.OFF);
Logger.getLogger("org.apache.ignite").setLevel(Level.OFF);
System.out.println("Reading data from Ignite table.");
Dataset<Row> peopleDF = spark.read()
.format(IgniteDataFrameSettings.FORMAT_IGNITE())
.option(IgniteDataFrameSettings.OPTION_CONFIG_FILE(), CONFIG)
.option(IgniteDataFrameSettings.OPTION_TABLE(), "people")
.load();
peopleDF.createOrReplaceTempView("people");
Dataset<Row> sqlDF = spark.sql("SELECT * FROM people WHERE id > 0 AND id < 6");
sqlDF.show();
System.out.println("Done!");
Ignition.stop(false);
}
}
在DFReader
中,初始化和配置與DFWriter
相同,這個應用會執行一些過濾,需求是查找所有的id > 0 以及 < 6的人,然後輸出結果。
在IDE中,通過下面的代碼可以啓動一個Ignite節點:
public class ExampleNodeStartup {
public static void main(String[] args) throws IgniteException {
Ignition.start("config/example-ignite.xml");
}
}
到此,就可以對代碼進行測試了。
運行應用
首先在IDE中啓動一個Ignite節點,然後運行DFWriter
應用,輸出如下:
JSON file contents:
+-------------------+---+------------------+
| department| id| name|
+-------------------+---+------------------+
|Executive Committee| 1| Ivan Ivanov|
|Executive Committee| 2| Petr Petrov|
| Production| 3| John Doe|
| Production| 4| Ann Smith|
| Accounting| 5| Sergey Smirnov|
| Accounting| 6|Alexandra Sergeeva|
| IT| 7| Adam West|
| Head Office| 8| Beverley Chase|
| Head Office| 9| Igor Rozhkov|
| IT| 10|Anastasia Borisova|
+-------------------+---+------------------+
Writing DataFrame to Ignite.
Done!
如果將上面的結果與JSON文件的內容進行對比,會顯示兩者是一致的,這也是期望的結果。
下一步會運行DFReader
,輸出如下:
Reading data from Ignite table.
+-------------------+--------------+---+
| DEPARTMENT| NAME| ID|
+-------------------+--------------+---+
|Executive Committee| Ivan Ivanov| 1|
|Executive Committee| Petr Petrov| 2|
| Production| John Doe| 3|
| Production| Ann Smith| 4|
| Accounting|Sergey Smirnov| 5|
+-------------------+--------------+---+
Done!
這也是期望的輸出。
總結
通過本文,會發現使用Ignite DataFrames是如何簡單,這樣就可以通過Ignite DataFrame進行數據的讀寫了。
未來,這些代碼示例也會作爲Ignite發行版的一部分進行發佈。
關於Ignite和Spark的集成,內容就是這些了。