环境:scala 版本2.11.8,spark 版本2.0.1,使用 Intellij IDEA 来开发。
准备工作:
创建maven项目
可以从官网上找到我们建项目时使用的 archetype
至于具体怎么创建项目,请参考一个朋友的文章Intellij IDEA 创建 spark/scala 项目
这个是前一段时间发现的一个朋友,强烈推荐大家去转转。
好了,这样一来就默认大家创建好了项目…
1 第一个例子
1.1 创建 SparkSession
官方文档如是说。
那么我们可以按照这个例子来写。
import org.apache.spark.sql.SparkSession
val spark = SparkSession
.builder()
.appName("sql test")
.master("local")
.getOrCreate()
import spark.implicits._
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
1.2 创建 DataFrames
//创建dataframe
val df = spark.read.json("C:\\Users\\Administrator\\Desktop\\people.json")
df.show()
// +----+-------+
// | age| name|
// +----+-------+
// |null|Michael|
// | 30| Andy|
// | 19| Justin|
// +----+-------+
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
就像官网写的那样,我们可以调用 show() 方法来打印出 df 的数据。这里我是把官网上的示例给放到了指定的目录。当然,我们也可以自己创建一个 json 文件,格式如下:
{"name":"Signal"}
{"name":"May j Lee","age":20}
{"name":"Jay Chou","age":36}
{"name":"Jack Chen","age":60}
- 1
- 2
- 3
- 4
- 5
当然,还有一些其他操作,我就不一一敲了,官网上给出的示例非常详细。用到类似的了就去官网上查…
我们还可以使用 SQL 语句来操作:
不过在我们使用 SQL 进行操作之前,需要使用 createOrReplaceTempView() 方法,熟悉 SQL 语句人肯定都知道”视图(view)“,接下来这个就是我们要操作的对象。
df.createOrReplaceTempView("people")
val sqlDF = spark.sql("select * from people")
sqlDF.show()
- 1
- 2
- 3
2 第二个例子
在第一个例子中,我们是根据一个 json 文件进行了一系列的操作,接下来我们是不是可以创建一个呢?
这里我们需要使用到的对象是 DataSets
2.1 创建 DataSets
我们还是参照官网的例子来写:
def createDataSetsTest(spark:SparkSession): Unit ={
import spark.implicits._
//创建 DataSet
val caseClassDS = Seq(Person("Jack",80),Person("Rose",76)).toDS()
caseClassDS.show()
//保存
caseClassDS.write.mode(SaveMode.Overwrite).json("C:\\Users\\Administrator\\Desktop\\SIGNAL-TEMP\\person.json")
val primitiveDS = Seq(1,2,3).toDS()
val ds = primitiveDS.map(_+1).collect()
ds.foreach(println)
val path = "C:\\Users\\Administrator\\Desktop\\SIGNAL-TEMP\\person.json"
val personDS = spark.read.json(path).as[Person]
personDS.show()
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
接下我们可以调用这个 createDataSets(…) 来看看到底发生了些什么事情。
object SqlJson {
case class Person(name:String,age:Long)
def main(args: Array[String]) {
val spark = SparkSession.builder().appName("spark json").master("local").getOrCreate()
import spark.implicits._
createDataFrameTest(spark)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
于是就像图片上那样,我们成功保存了 json 对象,并且我们还将它输出到了控制台。
这里大家可能疑惑的就是 SavaMode 了,别担心,官网有:
说起来保存,我们还可以保存为 parquet。
...
//保存
df.write.mode(SaveMode.Overwrite).parquet("C:\\Users\\Administrator\\Desktop\\SIGNAL-TEMP\\sparkSql.parquet")
//读取
val parquetFile = spark.read.parquet("C:\\Users\\Administrator\\Desktop\\SIGNAL-TEMP\\sparkSql.parquet")
parquetFile.where($"key"===1).select($"key",$"value".as("v")).collect().foreach(println)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
同样的,会在我们指定的路径下新建一个文件夹:
但是对于这个文件就没有那么友好了,我们看不懂^@^
3 Spark 与 Hive
我们可以通过 Spark 在 Hive 中创建一张表,并且导入数据。
这次我们需要将代码打成 jar 包,放到集群下去运行。
package spark.connect
import org.apache.spark.sql.SparkSession
/**
* Created by SIGNAL on 2016/11/28.
*/
object HiveTest {
val spark = SparkSession.builder().appName("Spark connect to Hive").enableHiveSupport().getOrCreate()
def main(args: Array[String]) {
import spark.implicits._
import spark.sql
val createTable = "create table if not exists spark_hive_test(col1 int,col2 string,col3 string) row format delimited fields terminated by '|'"
spark.sql(createTable)
sql("load data local inpath '/home/signal/spark_hive_test.txt' overwrite into table spark_hive_test")
val df = sql("select * from spark_hive_test")
df.show()
spark.stop()
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
Intellij IDEA 打 jar 包比较麻烦,不如 Eclipse 来的顺溜。
Ctrl + Alt + Shift + s 之后,出现 Project Structure,然后如图,然后自己倒腾…
…于是经过一番折腾之后,我以为大家 jar 包打好了。
然后我们可以发送到Linux上,方便操作就放到 master 节点上的 /homa/signal 目录下了:
大家还记得 hive 的建表语法吧,记得我们在建表时指定的分割符是什么不?
可以看到我们指定的分割符是”|“,而且,导入到 hive 中的时候我们指定了文件名和文件的路径,也就我们当前所在的 /home/signal,接下来我们需要在 /home/siganl 目录下创建一个 spark_hive_test.txt 的文件,文件格式如下:
[root@master signal]# vi spark_hive_test.txt
4|Signal|male
5|Kevin|male
6|Max|female
"spark_hive_test.txt" 3L, 40C written
[root@master signal]#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
这一系列操作完了之后,我们就可以运行 spark-submit 了。但是,我们需要确保的是 Mysql 的服务是启动的。
[root@master signal]# service mysql status
SUCCESS! MySQL running (1678)
[root@master signal]#
- 1
- 2
- 3
- 4
那么我们就”提交“吧:
[root@master signal]# spark-submit --class spark.connect.HiveTest --master[1] SparkHive.jar
...
+----+------+------+
|col1| col2| col3|
+----+------+------+
| 4|Signal| male|
| 5| Kevin| male|
| 6| Max|female|
+----+------+------+
16/11/28 19:46:35 INFO SparkUI: Stopped Spark web UI at http://192.168.38.129:4040
16/11/28 19:46:35 INFO MapOutputTrackerMasterEndpoint: MapOutputTrackerMasterEndpoint stopped!
16/11/28 19:46:35 INFO MemoryStore: MemoryStore cleared
16/11/28 19:46:35 INFO BlockManager: BlockManager stopped
16/11/28 19:46:35 INFO BlockManagerMaster: BlockManagerMaster stopped
16/11/28 19:46:35 INFO OutputCommitCoordinator$OutputCommitCoordinatorEndpoint: OutputCommitCoordinator stopped!
16/11/28 19:46:35 INFO SparkContext: Successfully stopped SparkContext
16/11/28 19:46:35 INFO ShutdownHookManager: Shutdown hook called
16/11/28 19:46:35 INFO ShutdownHookManager: Deleting directory /tmp/spark-59c859cc-611b-4aac-adce-567eb8376ffa
[root@master signal]#
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
控制台是正常输出了,我们可以到 Hive 中看看是否真的创建成功了。
启动 hiveserver2,然后使用 beeline 访问:
[root@master bin]# hiveserver2 & > /dev/null 2>&1
[1] 7712
[root@master bin]# beeline -u jdbc:hive2://master:10000 -n root
...
Connected to: Apache Hive (version 2.1.0)
Driver: Hive JDBC (version 2.1.0)
16/11/28 19:56:12 [main]: WARN jdbc.HiveConnection: Request to set autoCommit to false; Hive does not support autoCommit=false.
Transaction isolation: TRANSACTION_REPEATABLE_READ
Beeline version 2.1.0 by Apache Hive
0: jdbc:hive2://master:10000>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
我们可以看到,在 default 下是有 spark_hive_test 这张表的。
0: jdbc:hive2://master:10000> use default;
OK
No rows affected (0.243 seconds)
0: jdbc:hive2://master:10000> select * from spark_hive_test;
OK
+-----------------------+-----------------------+-----------------------+--+
| spark_hive_test.col1 | spark_hive_test.col2 | spark_hive_test.col3 |
+-----------------------+-----------------------+-----------------------+--+
| 4 | Signal | male |
| 5 | Kevin | male |
| 6 | Max | female |
+-----------------------+-----------------------+-----------------------+--+
3 rows selected (2.319 seconds)
0: jdbc:hive2://master:10000>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
真的就像我们在控制台里看到的那样,我们的hive中有了那张表,并且数据也加载进去了。
4 Spark 与 HBase
package spark.connect
import org.apache.hadoop.hbase.HBaseConfiguration
import org.apache.hadoop.hbase.client.Result
import org.apache.hadoop.hbase.io.ImmutableBytesWritable
import org.apache.hadoop.hbase.mapreduce.TableInputFormat
import org.apache.hadoop.hbase.util.Bytes
import org.apache.spark.{SparkConf, SparkContext}
/**
* Created by SIGNAL on 2016/11/28.
*/
object HBaseTest {
val conf = new SparkConf().setAppName("Spark connect to HBase").setMaster("local")
val sc = new SparkContext(conf)
def main(args: Array[String]) {
val hconf = HBaseConfiguration.create()
hconf.set(TableInputFormat.INPUT_TABLE,"student")
val hbaseRDD = sc.newAPIHadoopRDD(hconf,classOf[TableInputFormat]
,classOf[ImmutableBytesWritable]
,classOf[Result])
val rowRDD = hbaseRDD.map(x =>(Bytes.toString(x._1.get()), Bytes.toString(x._2.getValue("i".getBytes,"name".getBytes()))))
println(hbaseRDD.count())
rowRDD.foreach(println _)
sc.stop()
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
这个就没什么好说的了,跟我们使用 java 访问 HBase 差不太多,只不过我们这次使用的是 scala 。
确保我们的 hbase 启动,我们就可以在 Intellij IDEA 中运行了。
然后运行,我们会在控制台上看到 student 表中 i 列族下的 name 一列的数据了:
当然,我们有好多种运行方式,可以放到集群中去运行,还可以在 yarn 下运行。大家可以参照官网上 spark-submit 来操作,就不一一演示了。
5 Spark 与 Mysql
package spark.connect
import java.sql.{Connection, DriverManager}
import java.util.Properties
import org.apache.spark.rdd.JdbcRDD
import org.apache.spark.sql.SparkSession
import org.apache.spark.{SparkConf, SparkContext}
/**
* Created by SIGNAL on 2016/11/28.
*/
object MysqlTest {
val conf = new SparkConf().setAppName("Spark connect to Mysql").setMaster("local")
val sc = new SparkContext(conf)
def createConnection(): Connection ={
Class.forName("com.mysql.jdbc.Driver").newInstance()
// DriverManager.getConnection("jdbc:mysql://localhost:3306/test?user=root&password=signal")
DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","signal")
}
def formMysql(): Unit ={
val spark = SparkSession.builder.appName("spark connect to mysql").master("local").getOrCreate()
import spark.implicits._
val fromrd = spark.read.jdbc("jdbc:mysql://localhost:3306/gov?user=root&password=signal","app_user",new Properties())
fromrd.show()
}
def main(args: Array[String]): Unit = {
val mysqlData = new JdbcRDD(sc,createConnection,"select * from tb_user where user_id >= ? and user_id <= ? ",0,1000,3,r=>r)
mysqlData.map(r => (r.getLong("user_id"),r.getInt("age"),r.getString("user_name") )).foreach(println _)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
这个跟 HBase 一样,都是比较简单的操作,但是我只是从数据库中读取数据,往数据库中写数据都差不多,看看 API 很快就会上手,也就不写了。
这么一来,Spark SQL 也就介绍的差不多了,大家还有看不懂的就去看官方文档吧,多看看,对着敲几遍代码,去 API 里看看方法。