Spark跨集群写hive

项目场景:

我们有两个集群(ps:计算集群/存储集群),现在有个需求就是,计算集群运行Spark任务,从kafka取数据写到存储集群的hive。


过程介绍

1. 抽取数据文件

1.1 创建Spark入口对象指定源数据的Hive元数据服务

扩展:
1,在远程连接Hive时Hive有两种服务Hive Metastore Server和HiveServer2
HiveServer2是JDBC连接,使用这种方式会占用数据本地集群的计算资源(常用默认端口10000的那种)
2,Spark连接Hive可以使用Hive Metastore Server,这样只需连接Hive的元数据,通过元数据记录的数据路径拉取数据使用Spark对数据进行计算(常用默认端口9083的那种)

sparkConf.set("spark.streaming.kafka.maxRatePerPartition", maxRatePerPartition.toString)
      .set("spark.streaming.backpressure.enabled", "true")
      .set("spark.streaming.stopGracefullyOnShutdown", "true")
      .setAppName(applicationName)
      
val session: SparkSession = SparkSession.builder()
      .config(sparkConf)
      .config("hive.metastore.uris","thrift://xxxx:9083")
      .config("spark.sql.warehouse.dir","hdfs://xxxx:9000/user/hive/warehouse/")
      .enableHiveSupport()
      .getOrCreate()

1.2将Spark的hadoopConfiguration对象切换到存储数据集群

连接了存储集群的Hive Metastore Server元数据服务,Spark会根据里面记录的元数据信息去拉取数据,而计算集群记录的是其他HDFS集群的路径
默认根据配置文件本集群跑Spark程序时连接的是本集群的HDFS地址,所以根据元数据获取的数据路径会找不到
而MetaServer元数据服务地址属于在Spark创建时指定的,在这个对象生命周期内无法被改变,但是Hadoop相关配置是可以在运行时切换的
所以需要在取数时切换Hadoop配置

/***
   * @Author: lzx
   * @Description:
   * @Date: 2022/5/27
   * @Param session: bulid好的Sparkssion
   * @Param nameSpace: 集群的命名空间
   * @Param nn1: nn1_ID
   * @Param nn1Addr: nn1对应的IP:host
   * @Param nn2: nn2_ID
   * @Param nn2Addr:  nn2对应的IP:host
   * @return: void
   **/
  def changeHDFSConf(session:SparkSession,nameSpace:String,nn1:String,nn1Addr:String,nn2:String,nn2Addr:String): Unit ={

    val sc: SparkContext = session.sparkContext
    sc.hadoopConfiguration.set("fs.defaultFS", s"hdfs://$nameSpace")
    sc.hadoopConfiguration.set("dfs.nameservices", nameSpace)
    sc.hadoopConfiguration.set(s"dfs.ha.namenodes.$nameSpace", s"$nn1,$nn2")
    sc.hadoopConfiguration.set(s"dfs.namenode.rpc-address.$nameSpace.$nn1", nn1Addr)
    sc.hadoopConfiguration.set(s"dfs.namenode.rpc-address.$nameSpace.$nn2", nn2Addr)
    sc.hadoopConfiguration.set(s"dfs.client.failover.proxy.provider.$nameSpace", s"org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider")
  }

1.3 通过SQL指定需要获取的数据将数据加载到目标集群的HDFS文件中

在这里插入图片描述
同时在SQL中可以看到我在同步过来数据时将year, month, day字段拼成dt字段作为日期新字段,且原表数据中字段比这里多得多,只取了需要的字段以节省时间空间
并且在写出成HDFS文件的时候通过.partitionBy(“site”, “dt”)也指定了目标表的分区

写出的文件路径就是这种格式的:/tianchi/data/ods_app_burial_log/site=zz/dt=2022-06-11

另外$HDFS_ADDR是通过API动态获取的目标集群active nameNode的ip:port
防止写死后NN主备切换(因为存储集群配置了多NN,防止主备切换报错)

  /***
   * @Author: lzx
   * @Description:  获取当前状态位Active的NN节点
   * @Date: 2022/5/27
    
   * @return: java.lang.String
   **/
  def getActiveNN:String={
    val hadoopConf: Configuration = new Configuration
    val fs: FileSystem = FileSystem.get(hadoopConf)
    val activeNN: String = HAUtil.getAddressOfActive(fs).toString.split("/")(1)
    activeNN
  }

2.将导入的数据文件加载到存储集群的Hive表中

2.1 使用HiveSQL的语法加载数据
LOAD DATA INPATH '/datapath/' OVERWRITE INTO TABLE tableName PARTITION (par='xxx')
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值