Spark整合Hive

  • 整合hive元数据metadata
  • Hive 的 MetaStore 是一个 Hive 的组件
  • 而 Hive 的 MetaStore 的运行模式有三种
  • Hive开启元数据服务
  • 如果没有添加下面这一段,启动spark会报错
  • 启动hive元数据服务
  • 同时需要加载其他配置,包括HDFS
  • 测试


整合hive元数据metadata

  • MetaStore, 元数据存储
    SparkSQL 内置的有一个 MetaStore, 通过嵌入式数据库 Derby 保存元信息, 但是对于生产环境来说, 还是应该使用 Hive 的 MetaStore, 一是更成熟, 功能更强, 二是可以使用 Hive 的元信息
  • 查询引擎
    SparkSQL 内置了 HiveSQL 的支持, 所以无需整合

Hive 的 MetaStore 是一个 Hive 的组件

hue 连接spark spark连接hive的metastore_Hive

由上图可知道, 其实 Hive 中主要的组件就三个, HiveServer2 负责接受外部系统的查询请求, 例如 JDBC, HiveServer2 接收到查询请求后, 交给 Driver 处理, Driver 会首先去询问 MetaStore 表在哪存, 后 Driver 程序通过 MR 程序来访问 HDFS 从而获取结果返回给查询请求者

而 Hive 的 MetaStore 对 SparkSQL 的意义非常重大, 如果 SparkSQL 可以直接访问 Hive 的 MetaStore, 则理论上可以做到和 Hive 一样的事情, 例如通过 Hive 表查询数据

而 Hive 的 MetaStore 的运行模式有三种
  • 内嵌 Derby 数据库模式
    这种模式不必说了, 自然是在测试的时候使用, 生产环境不太可能使用嵌入式数据库, 一是不稳定, 二是这个 Derby 是单连接的, 不支持并发
  • Local 模式
    Local 和 Remote 都是访问 MySQL 数据库作为存储元数据的地方, 但是 Local 模式的 MetaStore 没有独立进程, 依附于 HiveServer2 的进程
  • Remote 模式
    和 Loca 模式一样, 访问 MySQL 数据库存放元数据, 但是 Remote 的 MetaStore 运行在独立的进程中
Hive开启元数据服务
[root@node01 apache-hive-2.1.1-bin]# cat conf/hive-site.xml 
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
      <name>javax.jdo.option.ConnectionUserName</name>
      <value>root</value>
  </property>
  <property>
      <name>javax.jdo.option.ConnectionPassword</name>
      <value>123456</value>
  </property>
  <property>
      <name>javax.jdo.option.ConnectionURL</name>
      <value>jdbc:mysql://node03:3306/hive?createDatabaseIfNotExist=true&useSSL=false</value>
  </property>
  <property>
      <name>javax.jdo.option.ConnectionDriverName</name>
      <value>com.mysql.jdbc.Driver</value>
  </property>
  <property>
      <name>hive.metastore.schema.verification</name>
      <value>false</value>
  </property>
  <property>
    <name>datanucleus.schema.autoCreateAll</name>
    <value>true</value>
 </property>

 <property>
	<name>hive.cli.print.current.db</name>
	<value>true</value>
</property>

<property>
	<name>hive.cli.print.header</name>
	<value>true</value>
</property>	

 <property>
		<name>hive.server2.thrift.bind.host</name>
		<value>node03</value>
   </property>
   
   <property>
	<name>hive.metastore.uris</name>
        <value>thrift://node03:9083</value>
   </property>
   
   <property>
	<name>hive.metastore.client.socket.timeout</name>
        <value>3600</value>
   </property>

<!--这一段配置是重点,将元数据访问配置为remote模式-->
<property>
  <name>hive.metastore.local</name>
  <value>false</value>
</property>

</configuration>
如果没有添加下面这一段,启动spark会报错
<!--这一段配置是重点,将元数据访问配置为remote模式-->
<property>
  <name>hive.metastore.local</name>
  <value>false</value>
</property>

错误如下:

19/10/06 18:25:19 WARN hive.metastore: Failed to connect to the MetaStore Server...
19/10/06 18:25:20 WARN hive.metastore: Failed to connect to the MetaStore Server...
19/10/06 18:25:21 WARN hive.metastore: Failed to connect to the MetaStore Server...
19/10/06 18:25:22 WARN metadata.Hive: Failed to access metastore. This class should not accessed in runtime.
org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient

Caused by: java.lang.reflect.InvocationTargetException: org.apache.hadoop.hive.metastore.api.MetaException: Could not connect to meta store using any of the URIs provided. Most recent failure: org.apache.thrift.transport.TTransportException: java.net.ConnectException: Connection refused (Connection refused)

启动hive元数据服务

  • 前提是启动了mysql服务(存储元数据)
service mysqld start
	nohup bin/hive --service metastore &
	nohup bin/hive --service hiveserver2 &
同时需要加载其他配置,包括HDFS

即使不去整合 MetaStore, Spark 也有一个内置的 MateStore, 使用 Derby 嵌入式数据库保存数据, 但是这种方式不适合生产环境, 因为这种模式同一时间只能有一个 SparkSession 使用, 所以生产环境更推荐使用 Hive 的 MetaStore

SparkSQL 整合 Hive 的 MetaStore 主要思路就是要通过配置能够访问它, 并且能够使用 HDFS 保存 WareHouse, 这些配置信息一般存在于 Hadoop 和 HDFS 的配置文件中, 所以可以直接拷贝 Hadoop 和 Hive 的配置文件到 Spark 的配置目录

cd /export/servers/hadoop/etc/hadoop
cp hive-site.xml core-site.xml hdfs-site.xml /export/servers/spark/conf/   

scp -r /export/servers/spark/conf node02:/export/servers/spark/conf
scp -r /export/servers/spark/conf node03:/export/servers/spark/conf

hive-site.xml : 要读取 Hive 的配置信息, 主要是元数据仓库的位置等信息
core-site.xml : 读取安全有关的配置
hdfs-site.xml: 有可能需要在 HDFS 中放置表文件, 所以需要 HDFS 的配置

测试
# 在hdfs中创建文件夹
hdfs dfs -mkdir -p /dataset

# 测试数据,要将该数据加载到创建的hive表中
vim stu
 xjm     22      xjm
 hhj     22      hhj

# 上传本地文件
hdfs dfs -put stu /dataset/

# 进入hive客户端创建hive表
bin/hive
CREATE DATABASE IF NOT EXISTS spark_integrition;

USE spark_integrition;

CREATE EXTERNAL TABLE student
(
  name  STRING,
  age   INT,
  gpa   string
)
ROW FORMAT DELIMITED
  FIELDS TERMINATED BY '\t'
  LINES TERMINATED BY '\n'
STORED AS TEXTFILE
LOCATION '/dataset/hive';

LOAD DATA INPATH '/dataset/stu' OVERWRITE INTO TABLE student;

# 启动spark,进入spark中sbin目录
./start-all.sh
# 开启一个客户端,进入bin目录
./spark-shell

hue 连接spark spark连接hive的metastore_Hive_02

...
Type in expressions to have them evaluated.
Type :help for more information.

scala> spark.sql
sql   sqlContext

scala> spark.sql
   def sql(sqlText: String): org.apache.spark.sql.DataFrame

scala> spark.sql("use spark_integrition")
res0: org.apache.spark.sql.DataFrame = []

scala> val resDF = spark.sql("select * from student limit 10")
resDF: org.apache.spark.sql.DataFrame = [name: string, age: int ... 1 more field]

scala> resDF.show()
+----+---+---+
|name|age|gpa|
+----+---+---+
| xjm| 22|xjm|
| hhj| 22|hhj|
+----+---+---+