上节课刻意的在什么外界都不用的情况下,spark自己就可以玩,外界不需要准备其它的,搭建环境,jvm都不需要,只要enableHiveSupport(),就可以包含的启动一个metastore,支持我们的DDL语句,等等操作,但是这节课主要讲贴近企业级的使用,在生产环境中是不会这么去玩的,强调一点:很多人学习架构的事情会很在意项目这件事情,但是如果学大数据,不要刻意的把项目放在心上,项目是被弱化的,大数据公司不可能启动了一个项目,为你准备了500台机器,然后把数据拷给你一份,几百T的数据,过两天又要启动一个项目,再给他准备500台机器,拷贝一份数据。在大数据里,整个公司可能就一个特别大的集群,然后所有公司数据都往里面扔,有一个平台的概念。到现在来说,已经衍生出中台的概念,项目这个词要弱化想成应用,我这家公司,有全公司所有部门web项目产生的数据,基于数据可以做很多的事情,可能是指标的分析,决策,风险评估,未来规划。无论做什么事情,是基于这些数据去推演,计算,加工的 。有的人会认为,每一项是独立的项目,之前在公司做日志项目,还做过风险评估的项目,可以这么去聊,但要往业务而不是大数据方面去带,我偏向分析哪些业务场景。但是无论业务,项目,分析的指标等等的这些事情,可以用另外一个维度的词汇代替,叫做应用。我拿着这些数据有哪些应用。
从数据在一家公司是要组建特别大的平台,我们是基于数据之上有不同的需求的时候,会开发很多的应用。随着开发应用越多,中台概念在大数据里很容易感受到的。可能有的公司没有业务平台,没有技术平台,但他迫切的需要数据平台,比如这个时候有很多的基于数据的开发,那么应用每开发一个都要从原表做起么?数据重新加工,或者每一个应用诞生都是需要所有的人员匹配,从数仓到java开发,所有环节都要接入么?这样有点累。这个时候大中台,小前台(应用),应用里面包含的技术量变低,把很多的计算从应用这个级别切出来,放到平台里去,平台也不是特别素的只包含原生的调用,可塑造型的接口,而是把公司未来很多可能出现的应用功能切出来之后,放到平台里,包成一个具备访问要求特别低,可能他只懂业务,不懂技术,只是知道要做风险评估的话需要哪些数据,哪些字段,哪些画像,哪些维度的东西,整个平台上面有标签系统,有血统系统,一大堆的东西,最终一个人,面向一个网页点几下,产生一个接口,这个接口放到前端里丰富出一个界面,小前端(应用)就出现了。
这个东西太概念了。国内做数据平台,做的比较不错的公司,做展示,实现原理和业务场景,能看见实打实的中台,不需要太多的技术就能撼动整家公司的流程。并不是要替代我们,每家公司数仓这个环节该有还是得有,中台只是一个引擎,只是在应用这个层面的时候不需要再投入大量的人了。但是在核心数据层面还是需要我们这样的人,去把数仓、平台做好,把数据准备好,但是如果一家公司频繁有前端应用开发的话,如果有一个中台就是效率极高的,仅此而已。

开始讲知识:

企业怎么去用这些技术的,spark-sql这些东西,enableHiveSupport() 等于这个元数据就在我这个application的生命周期里了,别的程序再去开发的时候,可能也要去弄一个enableHiveSupport() ,它是存一份重复的,而且数据之间还不能互访很尴尬,不可能这么去玩,所以到公司要不是平台,要不是高端一点就是中台的概念。在最开始的时候也画了一个图讲解SQL的执行流程,这里再偏向于高层次的去描述一个企业的处理过程,在一家公司,所有的数据会扔到一个统一的存储层,现在学的技术有hdfs或者hbase,hive的表是可以建在hbase上的,做一个映射关联。

有存储层之后,公司所有的设备,所有的内存,CPU,叫资源层,已知的可以接入各种技术整合的是yarn,比较公立的资源层,只要实现了它的applicatioin master接口,能够和它的resource manager通信,那个技术就能和yarn整合在一起,在资源层调度。这是两个最基础的层次,也是Hadoop生态的奠基者。这两个技术是在大数据开课前期第一阶段的 ,不复习了,一定要记住:所有的数据/资产都在这个里面准备好了,上方可能有很多垂直的应用。相应的kpi的统计,日志的分析,叫做应用层/业务层,可能每个应用是一个独立的业务,也可能几个应用是一个独立的业务,这些应用层怎么去访问下面的层次,中间差了计算层和管理层。

这个管理是比较片面的,spark-sql,更偏向于元数据的管理,一家公司这么多不同的应用,做在了一个整体的管理层上,hive的metastore,如果hive的metastore不能做到横向的全局管理的话,对数据有不同的抽象的话,会很麻烦,没必要每个项目组都重复造轮子,大家就一起使用一个metastore,不过计算层可以是MR,spark,tez。

hive metastore 运行不良 hive metastore高可用_hive

metaStore是贯穿全局的,hold住数据,hold住中间的计算,上层也可以访问它。spark是一个自己带driver(spark-sql-Driver不是core里的driver,这里更强调SQL解析的driver),并没有复用hive的driver,是完全可以独立的,只是应用了metastore。计算层里面还有hive的driver,使用自己的metastore。hive的driver底层还可以驱动spark,还可以驱动tez,MapReduce。都可以以SQL的形式,对外提供服务,都可以接受SQL的访问,基于HQL语句,但是hive的 driver 可以访问metastore,spark-sql的driver也可以访问meta store,但是向下计算的实现,hive-driver是mapreduce,spark,tez而spark-sql-Driver是spark-rdd core,这是一个逻辑拓扑图,整个推演的过程就更清楚了。
在公司会频繁的看到类似的结构,最值钱的就是hive的metastroe,因为有了它,全公司上下对元数据的管理就变得简单了,很多技术都可以在上面繁衍,比如说impala,也可以使用metastore,但是用C,C++开发的,它的计算并不是还要分层次,支持其他计算,它被制造出来就为了SQL,原生进程就在集群里,基于内存的计算方式,比spark还要快。
凸显的再重要一点,就是一定要反复练习的HQL,是一家公司技术层面 的SQL标准,在分布式大数据环境下的标准,有的人是能够完全实现它,有的人是它的子集,HQL非常完整强大,但是有一些技术能够实现,有一些技术因为计算的特征性,抛弃了一些慢的东西,有一些慢的操作就不支持了。
它的复杂度只是源于分布式的特点,主要在DDL这里,如何把公司的数据用DDL的方式管理映射起来,然后把数据还能在物理上分割、切割,比如分区分桶,查询其实函数,SQL语句这块,DQL查询这块,不趋向于某种技术。最简单的方式就是去访问hive的网站,把它所有的DDL,DML这些,语言的所有的example,用例先看一遍熟悉起来。

拓扑图理解了以后,进入物理的阶段:

hive metastore 运行不良 hive metastore高可用_hive metastore 运行不良_02

到公司要有能力去策划这个事情的,有工作经验的都知道,公司很多文档,大片的这样的架构图,图有了之后,还牵扯到集群的规划,相应的所有的清单和配置一堆的东西,一步一步来的。
如果我的metastore,不是想集成在本地启动这个程序里,想推到集群里的话,集群里需要有相应的进程。最基础的层次是基础设施层,yarn和hdfs是到一家公司最先要搭建起来的,在这节课不做,就拿之前搭建的集群,一共有4台机器,namenode是前两台,datanode是234台,resourcemanager是后两台,nodemanager是234,这4台机器完成了基础设施。
下一步应该有谁?
metastore,元数据管理,元数据存储的层次,之后就可以配置hiveserver2,beeline,hive的commandline interface 这个区域是第三步:相应的driver,在这个环节的时候,有个概念,有一些不是长服务,有一些是长服务。哪些是长服务?一会儿metastore,4台里会随便挑一台启动,有了之后,下一步就是driver,拿hive自身来说有hiveserver2,来访问metastore,hiveserver2要一直运行,它就是长服务,namenode,datanode,resourcemanager这些都是长服务,整个集群一启动就一直在那里运行,等着别人使用它。但有些东西它是短服务,比如hive自己,敲hive+回车,hive的commandline interface这就是短服务,写完了结束了。driver驱动的计算层,如果driver驱动的是mapReduce,每一个作业的提交都是一个短服务临时拉起的,并不是在那里持久运行的。短服务暴露一个问题,有启动和关闭的过程,启动的时候资源是否够,相对应的spark里面,也可以是短服务,只有一个metastore在集群里,剩下的什么东西都没有,因为可以令spark on yarn,集群里只需要有yarn就可以了,提交的时候,spark计算程序是短服务,spark application是短服务,计算结束所有资源收回,driver,execute都没有了,宏观上来说spark application是短服务,什么时候计算,什么时候启动,计算完就结束。但是,再较真一下,spark的程序,application可以随着集群启动,如果我让在集群启动完之后,就立刻启动了一个spark application,但是啥事都不做在那里等着,它也会申请一批的execute,进程一直存在,不碰它的话也不消失,但是资源已经申请到位了,进程已经启动完了。这时候如果有人给它发送了一个SQL,它快速把SQL转化成rdd,变成task任务,序列化反序列化发出去,然后变成task线程来执行,就减少了很多申请资源,driver启动,分配,回调的过程,所有spark是一个幽灵,比mapreduce更好一些。

实际操作:
把meta store和hive的使用支起来,最终看到的是整家公司只有一个metastore,所有先不碰spark,把整个公司的metastore和hive数仓这块的使用,接口和所有能力支起来。回到集群中:

1.启动hive
第一台:hive使用2.3.4的版本

cd /opt/hive-2.3.4
cd conf    //看配置项

现在说的hive自己,没有spark什么事情

vi hive-site.xml

如果想把一个meta store跑起来,这个进程在启动的时候,需要哪些配置项
1.一定要告诉他一个warehourse,就是它默认库default库保存的位置,在哪个目录下创建,一般会指向hdfs某一个目录,这是第一个配置项

<property>
    <name>hive.metastore.warehouse.dir</name>
    <value>/hive/warehouse</value>
</property>
<property>

2.剩下的配置项,因为 它是元数据管理,元数据需要持久化,所有下面是一系列jdbc连接MySQL这块的。它会拿MySQL做持久层,所有下面这些配置项都是围绕MySQL持久化连接信息的,就这么两个信息就可以让metastore启动起来了,因为metastore不做SQL解析,不做其他事情,只是能知道未来的数据存在哪个目录能做映射,只需要元数据能持久化到哪个数据库里,仅此而已。

<property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://node01:3306/hive?createDatabaseIfNotExist=true</value>
</property>
<property>
    <name>javax.jdo.option.ConnectionDriverName</name>
    <value>com.mysql.jdbc.Driver</value>
</property>
<property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>root</value>
</property>
<property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>ok</value>
</property>

集群里除了这台meta store需要这么多配置,集群中假设第三步的driver这里,未来无论是commendline interface,还是hiveserver2这两个可以解析SQL的东西,它如果想运行在哪台机器上,哪台机器还需要多一些配置,那么,需要多哪些配置?
234如果想启动hive的commendline interface,或者hiverserver2这两类角色启动,需要哪些配置?
也需要改hive-site文件,现在是空的,里面要加什么东西:
无论hive的命令行,命令接口的程序。还是hiveserver2,是个中转站,接受别人从jdbc发的SQL,解析完之后再咨询metastore,只需要metastore的地址。

<property>
    <name>hive.metastore.uris</name>
    <value>thirft://node01:9083</value>
</property>

未来只要写了这个配置项,这台机子无论启动hive的cli还是hiveserver2,它只要读到这个配置项,它的metastore就会连到node01上去,但是,如果这台机子配置文件是空的,这个没有写,请问hive的cli或者hiveserver2能不能启动?
能启动。它会默认有一个derby库,而且metastore,是可以和你的hiveserver2和hive cli整合在一起的。这一定要知道。

有时候会发现到公司进到一个项目小组里,发现哥几个都是刚培训出来的,操作元数据大家访问看到的东西不一样,那么配置一定出问题了。配置不统一,大家都没有指向同一个元数据库(metastore),所有在刚才,为什么要带搭建hive的过程,要找到感觉,自己的东西都要先指向知道metastore在哪里,那么其他技术,缺的是哪个配置,依然是metastore.uris那个协议的地址。所以其他技术,只要知道那个地址就可以使用metastore。

他们的所有技术的衔接点是靠什么衔接的,后续的也补充一下,每一台都加上metastore.uris的配置:

<property>
    <name>hive.metastore.uris</name>
    <value>thirft://node01:9083</value>
</property>

会发现整个集群的配置极其简单,在这里还要回顾一句话,hive就是个小程序而已,计算它不管,存储它不管,用的都是别的技术,所有它就是一个简单的jvm进程,数据存储用hdfs和hbase,元数据存储用MySQL,它自己就有点内存里映射的东西而已。顶多就它自己的driver里还有一些sql解析,转换成mapreduce计算xml配置文件生成的过程,这还稍显复杂一点,仅此而已。
都搞定之后要确认一下service,

service mysqld status

跑起来之后,所有的服务service都搞定了,为啥要看跑起来没有,因为我们的MySQL就是node01的:

<property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://node01:3306/hive?createDatabaseIfNotExist=true</value>
</property>

如果MySQL也有了,相应的hdfs,Hadoop生态都有了之后,就可以启动hive的metastore,请问怎么启动?
在node01上开启metastore:

hive --help
语法:Usage ./hive <parameters> --service serviceName <service parameters>
帮助:For help on a particular service:   ./hive --service serviceName --help
hive --service --help
可以使用的services:Available Services: beeline cleardanglingscratchdir cli help hiveburninclient hiveserver2 hiveserver hwi jar lineage metastore metatool orcfiledump rcfilecat schemaTool version
hive --service metastore

注意meta store是不接受SQL的,只是维护元数据管理这块的,所有如果写在hive里面向数仓写SQL有两个东西可以用。
第一个:hive 等同于 hive --service cli 可以启动hive的cli commandline interface
第二个:
这这里创建一张表:

show databases;
show tables;
create table user01(name string);    //在默认库下建一张表
show tables;                         //看到user01表出现了

底层的本质一定要清楚,是我们动用了hive的commandline interface,把SQL写进去之后,它自己动用了元数据,把建表语句通知给了metastore,最终存在了MySQL里面,如果有MySQL

mysql -uroot -pok
show databases;               //会有一个hive库
use hive
show tables;                  //这里面会有一张表  TBLS
select TBL_NAME  from TBLS;   //就能看见刚才建的user01这张表

在hive中建的所谓的表的元数据,会存在MySQL的表里变成记录,未来你的metastore会从记录中查出来,变成元数据,给hive或其他的变成schema元数据来使用。
这是所有的任何角色任何技术的依赖关系,他们怎么去使用的,继续验证,第一台启动了一个metastore,在第二台里用一个命令行接口就可以写SQL了,还有另外一种方式,整个公司不允许使用命令行接口,因为大家都必须要登陆到服务器上,但是服务器是不允许登陆的,我在集群里面启动一个东西,hive --service hiveserver2这个进程, 整个公司只需要在集群里面启动两个进程,一个是metastore,一个是hiveserver2,这两个进程,metastore是负责hive cli和hiveserver2给他们提供服务的,hiveserver2跑起来之后,在这个世界上,只要找一台机器,能够和node进行tcp通信,不需要从远程ssh登陆进来, 不需要知道这台操作系统的密码,只要能够和他进行tcp通信就可以了,在任何位置可以使用jdbc的连接,在集群里集群外都可以使用它了。
在node03上开启hiveserver2:

hive --service hiveserver2

用另外一台node04来假设一下,假设node04是另外一台机器或者在集群外,它只需要beeline,是通用的一个工具,在它里面可以触发连接,连接jdbc这个协议,冒号,hive2(代表hiveserver2这个schema),开启的对谁的连接,注意要连的是jdbc这个协议,而且要发送的是SQL,这个SQL解析要交给谁,metastore是不具备SQL解析能力的,只有hiveserver2是具备SQL解析的,所有hiveserver2是在哪里,node03上,且端口号是10000回车,输入所谓用户名root,密码无所谓,就可以连接进来了。连接进来之后依然可以show databases查看有哪些库
在node04上发起连接:

beeline
!connect jdbc:hive2://node03:10000
Enter username for jdbc:hive2://node03:10000: root
Enter password for jdbc:hive2://node03:10000: 随便输入
连接成功了
show databases;

这时候hiveserver2就趋向于是一个长服务了。
hive自己基于on metastore来实现的SQL的分布式解析框架就讲完了。
单点故障的问题:
在配置metastore.uris的时候,是个复数,metastore是可以启动多个的,而且其实这个并不是重点,重点要明白无论MySQL还是hive,元数据在一家公司,它的变化的频率是趋向于稳定的。每家公司不可能天天的创建表删除表修改表,一般一个需求下来之后先规划表,表创建完基本上元数据就不会动了,只要保证用的时候metastore挂了把它启动起来就可以了,它的访问频度并不是很高,只不过现在分布式这事情好聊,在MySQL里是整个的一个程序,挂了连SQL解析,元数据管理什么都没有了,只不过在分布式的时候分开了,被分出去的每个角色,角色与角色之间有自己的特征,hiveserver2如果挂了,metastore留着没有任何意义,这都不能发起执行了,但你hiveserver2起了执行报错,你把metastore启动一下就ok了。元数据都访问的同一个MySQL的一端,MySQL是一个,等于做了一个负载均衡,仅此而已。
为什么说学impala这个技术,上来就是把hive的元数据偷走,把metastore全拿走,到它那边玩去,你这边异步的什么时候给你同步一下,没有一个绝对实时同步的过程,变化的元数据修改这块要求的能力不是特别的强。
已经可以下出定义来了,在公司的整个集群当中虽然spark-sql的driver没有,但是hive相应的一系列东西都已经跑起来了,如果公司里说搭一个数仓就是拿hive这块来说事,数仓已经有了。
只不过我们现在需要快速的计算,迭代计算的时候,可能是趋向于spark-sql或者impala去解决更快的计算速度。但是稳定性等还有低配置要求能力是没有hive这边强一些,后续这边怎么实现的。
如果拿着idea和代码如何去利用刚才建的那张表?公司不是从0到1,公司已经有一个数仓了,有一个hive那边的小组了,你入职了,大家说要用spark-sql那些东西来计算,你怎么办?从配置过程中是可以看出来的。

object lesson05_sql_onhive {
  def main(args: Array[String]): Unit = {
    val ss: SparkSession = SparkSession
      .builder()
      .appName("test on hive")
      .master("local[*]")   //我这个spark程序所有的计算还是local本机去跑,但是所有的数据/元数据我本机这个sparksession里面没有,我需要集成hive的metastore,下面要怎么整合进来
      .config("hive.metastore.uris", "thrift://node01:9083")
      .enableHiveSupport()     //开启hive支持
      .getOrCreate()
    val sc: SparkContext = ss.sparkContext
    sc.setLogLevel("ERROR")
  }
}

我这个spark程序所有的计算还是local本机去跑,但是所有的数据/元数据我本机这个sparksession里面没有,我需要集成hive的metastore,下面要怎么整合进来,根据刚才的描述,整合metastore就靠的metastore的uris,所有在这里只需要加入hive.metastore.uris,后面给出的是thrift://node01:9083,只要给你讲清楚一个技术,你在后续学习的时候,就可以自己推导这个过程。有人说到公司第一件事情就是复制粘贴,其实是公司怕你不太懂它的原理。
这个时候我都集成它了是期望使用hive的相应的功能的,更想使用它的DDL的相应的东西,下面的配置项一定要开启enableHiveSupport() ,这两个是成对出现的,getOrCreate()得到一个session,整套逻辑为什么要写这个配置项,每个字符应该都背死了。
以上只是完成了对hive元数据的访问的东西,下面注意看,第一次运行,请问ss.catalog是spark自己的,曾经看一个application启动的时候catalog是空的,请问现在listTables().show()能不能看到表。

ss.catalog.listTables().show()
//之前如果想写sql语句,如果没有hive的时候,sql里的表哪来的?
//一定是dataSet/DataFrame通过创建createTempleView
//但现在从来没有读去过什么文件,也没有得到过DataSet和DataFrame,这里面能不能写sql看到一些东西?
val df: DataFrame = ss.sql("show tables")
df.show()

看到啥,一共有两次打印,第一个打印来自于spark的catalog,只要集成了hive的metastore,其实访问catalog是可以访问全局的hive的metastore里的元数据的,刚才创建的user01表,下面的show tables();显示的也是metastore里的表。
输出结果:

+------+--------+-----------+---------+-----------+
|  name|database|description|tableType|isTemporary|
+------+--------+-----------+---------+-----------+
|user01| default|       null|  MANAGED|      false|
+------+--------+-----------+---------+-----------+

+--------+---------+-----------+
|database|tableName|isTemporary|
+--------+---------+-----------+
| default|   user01|      false|
+--------+---------+-----------+

注意看这样一个操作:
在spark session启动的时候,准备了一个数据集,并且createTempView(),注意看上面这两个操作打印的是什么东西?以及一会儿去hive的元数据库看能不能看到表?

import ss.implicits._
val df01: DataFrame = List(
  "zhangsan",
  "lisi"
).toDF("name")
df01.createTempView("ooxx")

输出结果:无论catalog还是metastore看到的东西都是一样的,都有user01和ooxx

+------+--------+-----------+---------+-----------+
|  name|database|description|tableType|isTemporary|
+------+--------+-----------+---------+-----------+
|user01| default|       null|  MANAGED|      false|
|  ooxx|    null|       null|TEMPORARY|       true|
+------+--------+-----------+---------+-----------+

+--------+---------+-----------+
|database|tableName|isTemporary|
+--------+---------+-----------+
| default|   user01|      false|
|        |     ooxx|       true|
+--------+---------+-----------+

但是有一个单独的列 isTemporary 是不是临时表,什么意思,只在application的内存里有用,所以去hive里验证的话,还只能看到一个user01,继续完善,刚才是得到的数据集注册到catalog,可以看到metastore持久化的表和临时的表,但如果在打印之前再做一个操作

ss.sql("create table xxoo (id int)")   //明显是DDL语句

这个DDL创建的这张表,能不能成功,以及去hive看会有什么后果?
要知道未来在写SQL的时候哪些是持久的,哪些是临时的。
首先无论哪种操作,面向spark的catalog,全局都能看到,然后ooxx也建出来了,而且显示的时候 isTemporary 是false

备注一个错误:Exception in thread “main” org.apache.spark.sql.AnalysisException: org.apache.hadoop.hive.ql.metadata.HiveException: MetaException(message:Got exception: org.apache.hadoop.security.AccessControlException Permission denied: user=chaokeaimuzhi, access=WRITE, inode="/hive/warehouse":root:supergroup:drwxr-xr-x
解决方案参考:
在环境变量中添加 HADOOP_USER_NAME root ,重启IDEA即可解决
输出结果:

+------+--------+-----------+---------+-----------+
|  name|database|description|tableType|isTemporary|
+------+--------+-----------+---------+-----------+
|user01| default|       null|  MANAGED|      false|
|  xxoo| default|       null|  MANAGED|      false|
|  ooxx|    null|       null|TEMPORARY|       true|
+------+--------+-----------+---------+-----------+

+--------+---------+-----------+
|database|tableName|isTemporary|
+--------+---------+-----------+
| default|   user01|      false|
| default|     xxoo|      false|
|        |     ooxx|       true|
+--------+---------+-----------+

图上画的逻辑spark-sql的driver和metastore是有一个互动过程的,只不过那些临时的表isTemporary是在它的内存里,剩下的DDL语句创建的和原有的都会在metastore进行同步。
把它稍微补全一下,能不能执行DML语句:

ss.sql("insert into xxoo values (8),(3),(6),(7)")
df01.write.saveAsTable("oxox")

这里是一个极其丰富灵活的交互形式,把数据存到所谓的表里,这个存的逻辑代码是在local本机执行的,那么这些数据最终存到哪里去?是hive的metastore里去了么?没有,数据最终落地到由metastore指向的那个warehouse,默认库的位置,就是hdfs里去,最终spark只有元数据和metastore交互,剩下的该跟什么层(和资源层提程序,和存储层提数据)单独去访问的。所谓的spark程序的output输出,它是输出到hdfs,元数据指定的表应该在什么目录下,这个时候,程序通过上面的配置,可以知道我hive的metastore元数据访问谁,但是如果想访问hdfs是不是差东西,差配置项。一般怎么去做。
最少最少需要hdfs-site.xml和core-site.xml的,core-site.xml指定了入口,是hdfs://mycluster,但是mycluster是一个字符串,通过hdfs-site.xml这个配置文件,继续将它解析成了两个逻辑字符串,分别解析成了物理主机和端口号。把它整体拷贝到spark项目中,粘贴一下,一定要注意是resources放配置文件的。

再来跑这个程序。数据能不能放进去,能不能存成这张表。执行完了没有报错。
在hive中查询

show tables;   //这个语句提交给了hive的命令行接口

hive的命令行接口怎么知道这三条记录的?
它先访问了hive的metastore,这个后台服务,它访问自己持久的MySQL,MySQL所有建表的东西会存在TBLS,这里面每个表隶属于一个DB_ID,哪个数据库。

一会儿讲除了IDEA没有它,公司里怎么去写SQL。

企业级使用的时候,无论在哪,spark程序是单机的还是分布式的,只要是spark程序,第一个要有的是spark driver,未来执行到SQL的时候,里面有sparkContext,sparkSession,最终是要知道metastore在哪,所以要先把metastore在哪告诉spark程序,而在这个环节。spark程序可以运行成什么样子?
现在就node01上启动了一台hive metastore
把node03上的hiveserver2关闭。
spark有很多种模型可以使用,比如它的资源层可以有多种,spark可以用standalone的方式下运行,它的资源层是自己的master worker,也可以是把资源层换成yarn,目前集群里有yarn,就没有必要单独启动一套自己的master 和 worker,可以直接用它,而且spark如果直接用的话,只要有一台机器有这个东西就可以了。一会儿提交程序的时候一定是 --master yarn,让yarn来调度它的driver在哪台启动这个jvm,spark on yarn是比较轻量级的。关键是怎么去用?
spark配置文件有一个spark-defaults.conf这是关于它自己的配置,还有spark-env是环境变量的配置,spark-defaults.conf这是关于spark程序未来运行时的配置项。目前来说给出了yarn未来上传jar包的路径,启动的时候会快一点。
spark-defaults.conf

#spark.eventlog.enabled           true
#spark.eventLog.dir               hdfs://mycluster/spark_log
#spark.history.fs.logDirectory    hdfs://mycluster/spark_log
#spark.yarn.jars                  hdfs://mycluster/work/spark_lib/jars/*

spark-env.sh 这里面给出的配置项有哪些:
有一个非常重要的配置项就可以了:HADOOP_CONF_DIR

export HADOOP_CONF_DIR=/opt/hadoop/etc/hadoop

这个目录要给出,未来spark程序就像原来单机程序一样,在单机开发的时候都需要一个resource配置,所以这两者是相似的,集群里只要给出配置的位置就可以读到配置文件,未来spark程序如果想写程序到hdfs在这里可以解析出来。如果想访问yarn的resourcemanager读取配置文件也可以读取到。这个配置项的意义,整个配置文件只要写这个就可以了 。

如何把spark和hive打通,就是关键的配置项,应该写在哪个文件合适?
只需要在spark-defaults.conf 加上一个

hive.metastore.uris    thrift://node01:9083

spark未来读到这个配置项的时候,就可以知道有这么一个hive的metastore可以访问,会发现整个spark程序就指向了一个基础设施层有个配置目录,告诉它metastore应该连谁,当做完之后,退出。

曾经用过的spark-shell,怎么启动?

spark-shell   --master  yarn    //告诉它是分布式的,而且是以yarn的方式来启动它

on yarn的时候关注的是8088,yarn资源层一会儿是不是会跑出一个spark程序来。
读它的配置项提示了一个东西:

Spark context available as 'sc' (master = yarn, app id = application_1606031668306_0002).
Spark session available as 'spark'.

所以底下可以这么去写:

scala> spark.sql("show tables").show()
+--------+-----------+-----------+
|database|  tableName|isTemporary|
+--------+-----------+-----------+
| default|       oxox|      false|
| default|     user01|      false|
| default|       xxoo|      false|
+--------+-----------+-----------+

在IDEA当中是怎么去写的,现在就怎么写,只不过由idea变成了命令行。
如果spark-defaults.conf配置项被忽略了,
Warning: Ignoring non-Spark config property: hive.metastore.uris=thrift://node01:9083
所以写在spark-default.conf是不对的,要单独写一个hive-site.xml的配置文件。
可以把hive-site.xml文件拷贝过来,在这个配置文件中去写,把原来的配置properties全删掉换上新的:

<property>
    <name>hive.metastore.uris</name>
    <value>thirft://hadoop100:9083</value>
</property>

这次就可以了。现在可以写sql了而且不需要IDEA在集群里可以用了。
但是这个模式有点像hive cli的方式,要登陆到集群里,启动一个spark-shell,每次写sql还要加上spark.sql("")的方式。不像是一个企业级在任何位置都可以向它去发送SQL语句,但是要明白一个道理,spark-shell这个级别把它跑起来之后,在整个集群中就会出现一个spark的application长运行。我这里不停,它一直处于running状态。且这个application还持有了一些container。而且可以通过页面知道driver默认的端口号是4040,访问的时候可以看到它持有了一些executor,一个driver在node01,两外两个executor在node04和node03,也可以在node04和node03上看到CoarseGrainedExecutorBackend,不能说它是一个长服务,只不过这个程序没有退出而已。未来写的SQL会稍微快一些。因为不像hive,如果在hive里写个SQL还复杂一点的话,就会触发成MapReduce,会冷拉起的过程,同样复杂的SQL写给spark的话,不需要冷拉起,因为executor进程已经在运行,只需要解析,发出去变成线程,立刻就跑起来了,资源已经申请好了。
这种方式虽然很好,但是离SQL的形式有点远,还不可以远程连接。
spark除了有spark-shell之外还有spark-sql

spark-sql --master yarn

再来看application没有了,spark-sql跑起来了已经开始运行了,是running状态,可以看到也是申请了containers,这时候不是spark-shell了,单独提供了一个spark-sql

spark-sql> show tables;
default oxox    false
default user01  false
default xxoo    false
spark-sql> create table xoxo (name string);
spark-sql> show tables;
default oxox    false
default user01  false
default xoxo    false
default xxoo    false

spark-sql这里可以直接写SQL了,上节课也演示过,spark session拿到手之后可以写一个死循环等着别人的输入,输入一个字符串可以放到session.sql的方法里面,然后帮它调起,把结果回显出来也可以。spark-sql这边并不神奇,关键看hive这边,也可以看到新创建的表。也就是说hive这里和spark共享了一个元数据,所以建表的DDL语句,只要在一边创建完,另外一边也可以享受了。
在企业中测试环节就可以使用这种方式了,但这就更像hive当中的command line interface,spark-sql更像的命令行接口,只能从命令行直接接SQL字符串还是不够优美,再优美一点行不行,把spark-sql结束,整个集群里关于spark的东西全结束了。
现在jps能看到的要不是hive的,要不是基础设施层的(存储层或资源层),现在能不能启动一个类似于曾经hive的hiveserver2,跑起来,可以在任何的位置面向这个类似hiveserver2的服务发送SQL,由这个服务来跑spark程序。
先跑起来一个spark程序,不在命令行接受SQL,而是要对外暴露jdbc的服务,让所有人通过beeline的形式来提交SQL语句。(想跑一个spark程序application,刚才spark-shell和spark-sql已经能访问metastore了,现在spark能够访问了,需要做的并不多,只要找到有没有这个程序)
有的,在sbin目录下,这个东西才叫长服务,一般伴随着集群启动的时候要把它启动起来,它会有一个start-thriftserver.sh,现在yarn中没有任何活动的application,然后只需要启动它:

./start-thriftserver.sh   --master yarn

因为这个东西是想跑一个分布式的,对外提供jdbc服务的这么一个服务,跑起来,就会看到一个sparkSubmit的进程,8088端口刷新就会多了一个Thrift JDBC/ODBC Server,当它跑起来了,后面的事情都不需要教了。
只需要找一个beeline的程序,最好的版本是它自己带的,在bin目录下自带了一个beeline

cd /opt/spark245/bin/
./beeline
Beeline version 1.2.1.spark2 by Apache Hive
beeline>!connect jdbc:hive2://node01:10000
20/11/23 16:20:53 INFO jdbc.Utils: Supplied authorities: node01:10000
20/11/23 16:20:53 INFO jdbc.Utils: Resolved authority: node01:10000
20/11/23 16:20:54 INFO jdbc.HiveConnection: Will try to open client transport with JDBC Uri: jdbc:hive2://node01:10000
Connected to: Spark SQL (version 2.4.5)
Driver: Hive JDBC (version 1.2.1.spark2)
Transaction isolation: TRANSACTION_REPEATABLE_READ
0: jdbc:hive2://node01:10000>

连接以jdbc协议,hive2的schema,(虽然连接的是spark的thrift server但是它的jdbc协议还是hive2的,它照抄的是hive的metastore的HQL语法),然后连接的是node01上面的10000端口号。

0: jdbc:hive2://node01:10000>show tables;
+-----------+--------------+--------------+--+
| database  |  tableName   | isTemporary  |
+-----------+--------------+--------------+--+
| default   | oxox         | false        |
| default   | user01       | false        |
| default   | xoxo         | false        |
| default   | xxoo         | false        |
+-----------+--------------+--------------+--+

现在如果在集群外是不是也可以通过jdbc的方式访问已经启动好的jdbc的thrift server了。如果是一家公司的决策者,技术总监,架构师。公司这么多人要用到关于SQL的对数据的加工,应该暴露哪种服务形式,分发Linux系统账号密码登陆执行spark-shell和spark-sql还是启动thrift server在其他地方通过jdbc连过来执行。
这个知识点是重叠的,因为无论hive还是spark都希望暴露的是thrift server。这才是正经企业级应该使用的方式,无论到什么level的公司都应该会用了,还有一种方式后面讲完cloudera再说。