Kudu與Spark 集成

1.環境

 <properties>
    <scala.version>2.11.8</scala.version>
    <spark.version>2.2.0</spark.version>
    <kudu.version>1.5.0</kudu.version>
  </properties>

2.測試代碼

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.types.{StringType, StructField, StructType}
import org.apache.kudu.client._
import collection.JavaConverters._

object KuduApp {
  def main(args: Array[String]): Unit = {

    val spark = SparkSession.builder().appName("KuduApp").master("local[2]").getOrCreate()

     //Read a table from Kudu
    val df = spark.read
          .options(Map("kudu.master" -> "10.19.120.70:7051", "kudu.table" -> "test_table"))
          .format("kudu").load
        df.schema.printTreeString()


//    // Use KuduContext to create, delete, or write to Kudu tables
//    val kuduContext = new KuduContext("10.19.120.70:7051", spark.sparkContext)
//
//
//    // The schema is encoded in a string
//    val schemalString="id,age,name"
//
//    // Generate the schema based on the string of schema
//    val fields=schemalString.split(",").map(filedName=>StructField(filedName,StringType,nullable =true ))
//    val schema=StructType(fields)
//
//
//    val KuduTable = kuduContext.createTable(
//     "test_table", schema, Seq("id"),
//     new CreateTableOptions()
//       .setNumReplicas(1)
//       .addHashPartitions(List("id").asJava, 3)).getSchema
//
//    val  id  = KuduTable.getColumn("id")
//    print(id)
//
//    kuduContext.tableExists("test_table")
  }
}

現象:通過spark sql 操作報如下錯誤:

Exception in thread "main" java.lang.ClassNotFoundException: Failed to find data source: kudu. Please find packages at http://spark.apache.org/third-party-projects.html
	at org.apache.spark.sql.execution.datasources.DataSource$.lookupDataSource(DataSource.scala:549)
	at org.apache.spark.sql.execution.datasources.DataSource.providingClass$lzycompute(DataSource.scala:86)
	at org.apache.spark.sql.execution.datasources.DataSource.providingClass(DataSource.scala:86)
	at org.apache.spark.sql.execution.datasources.DataSource.resolveRelation(DataSource.scala:301)
	at org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:178)
	at org.apache.spark.sql.DataFrameReader.load(DataFrameReader.scala:146)
	at cn.zhangyu.KuduApp$.main(KuduApp.scala:18)
	at cn.zhangyu.KuduApp.main(KuduApp.scala)
Caused by: java.lang.ClassNotFoundException: kudu.DefaultSource
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at org.apache.spark.sql.execution.datasources.DataSource$$anonfun$21$$anonfun$apply$12.apply(DataSource.scala:533)
	at org.apache.spark.sql.execution.datasources.DataSource$$anonfun$21$$anonfun$apply$12.apply(DataSource.scala:533)
	at scala.util.Try$.apply(Try.scala:192)
	at org.apache.spark.sql.execution.datasources.DataSource$$anonfun$21.apply(DataSource.scala:533)
	at org.apache.spark.sql.execution.datasources.DataSource$$anonfun$21.apply(DataSource.scala:533)
	at scala.util.Try.orElse(Try.scala:84)
	at org.apache.spark.sql.execution.datasources.DataSource$.lookupDataSource(DataSource.scala:533)
	... 7 more

而通過KuduContext是可以操作的沒有報錯,代碼爲上面註解部分

3 解決思路

查詢kudu官網:kudu官網

官網中說出了版本的問題:
如果將Spark 2與Scala 2.11一起使用,請使用kudu-spark2_2.11工件。
kudu-spark版本1.8.0及更低版本的語法略有不同。有關有效示例,請參閱您的版本的文檔。可以在發佈頁面上找到版本化文檔。
spark-shell --packages org.apache.kudu:kudu-spark2_2.11:1.9.0
看到了 官網使用的是1.9.0的版本.

但是但是但是:
官網下面說到了下面幾個集成問題:

  1. Spark 2.2+在運行時需要Java 8,即使Kudu Spark 2.x集成與Java 7兼容。Spark 2.2是Kudu 1.5.0的默認依賴版本。

  2. 當註冊爲臨時表時,必須爲名稱包含大寫或非ascii字符的Kudu表分配備用名稱。

  3. 包含大寫或非ascii字符的列名的Kudu表不能與SparkSQL一起使用。可以在Kudu中重命名列以解決此問題。

  4. <>並且OR謂詞不會被推送到Kudu,而是由Spark任務進行評估。只有LIKE帶有後綴通配符的謂詞纔會被推送到Kudu,這意味着它LIKE "FOO%"被推下但LIKE "FOO%BAR"不是。

  5. Kudu不支持Spark SQL支持的每種類型。例如, Date不支持複雜類型。

  6. Kudu表只能在SparkSQL中註冊爲臨時表。使用HiveContext可能無法查詢Kudu表。

那就很奇怪了我用的1.5.0版本報錯爲:找不到類,數據源有問題

但是把kudu改成1.9.0 問題解決

運行結果:

root
 |-- id: string (nullable = false)
 |-- age: string (nullable = true)
 |-- name: string (nullable = true)

4 Spark集成最佳實踐

  1. 每個羣集避免多個Kudu客戶端。
    一個常見的Kudu-Spark編碼錯誤是實例化額外的KuduClient對象。在kudu-spark中,a KuduClient屬於KuduContext。Spark應用程序代碼不應創建另一個KuduClient連接到同一羣集。相反,應用程序代碼應使用KuduContext訪問KuduClient使用 KuduContext#syncClient。
  // Use KuduContext to create, delete, or write to Kudu tables
    val kuduContext = new KuduContext("10.19.120.70:7051", spark.sparkContext)

    val list = kuduContext.syncClient.getTablesList.getTablesList
    if (list.iterator().hasNext){
      print(list.iterator().next())
    }
  1. 要診斷KuduClientSpark作業中的多個實例,請查看主服務器的日誌中的符號,這些符號會被來自不同客戶端的許多GetTableLocations或 GetTabletLocations請求過載,通常大約在同一時間。這種症狀特別適用於Spark Streaming代碼,其中創建KuduClient每個任務將導致來自新客戶端的主請求的週期性波。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章