Spark读入ProtoMessage并写出为Parquet

该博客讲述了如何在Spark项目中将按照ProtoBuf格式存储的文件转换为Parquet。作者首先介绍了问题背景,然后详细说明了环境准备,包括proto文件、插件配置和依赖文件的准备。接着,提出了两种解决方案:一是通过ProtoSQL将ProtoMessage转换为DataFrame再写入Parquet,但由于性能问题而被放弃;二是直接在Executor中将ProtoMessage写为Parquet,该方案大大提升了性能,使耗时从10小时降低到21分钟。

问题背景

最近Spark项目里有这样一个需求:需要从HDFS的某个目录下读入一些文件,这些文件是按照proto文件存储的ProtoMessage,现在需要把它们转换成Parquet存储,以供SQL查询。

环境准备

1. 准备proto文件:person_entity.proto

syntax = "proto3";
message Person { // 定义Person结构体
    enum Gender { // 定义性别,为枚举类型,值为男性(Male)或者女性(Female)
        Male = 0;
        Female = 1;
    }
    string name = 1; // 定义Person结构体中的名称属性,类型为string
    uint32 age = 2; // 定义Person结构体中的年龄属性,类型为uint32
    Gender gender = 3; // 定义Person结构体中的性别属性,类型为Gender
    // Parquet中不支持自身嵌套自身的类型,因此将该字段注释
    // repeated Person_Entity children = 4; // 定义Person结构体中的孩子属性,类型为Person的列表类型
    map<string, string> education_address_map = 5; // 定义上学阶段->上学地址的map映射
}

怎么生成java文件可以参考:初识Protobuf

2. 准备插件:project/assembly.sbt

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.6")
addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.27")
libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.10.0"

3. 准备项目依赖文件:build.sbt

name := "protobuf_test"

version := "0.1"

scalaVersion := "2.12.12"

libraryDependencies ++= Seq(
  "com.google.protobuf" % "protobuf-java" % "3.5.0",
  "com.google.guava" % "guava" % "16.0.1",
  "org.apache.spark" %% "spark-core" % "3.2.1" % "provided",
  "org.apache.spark" %% "spark-sql" % "3.2.1" % "provided",
  "com.thesamet.scalapb" %% "sparksql-scalapb" % "0.11.0-RC1",
)

PB.targets in Compile := Seq(
  scalapb.gen() -> (sourceManaged in Compile).value
)
assemblyShadeRules in assembly := Seq(
  ShadeRule.rename("com.google.protobuf.**" -> "shadeproto.@1").inAll,
  ShadeRule.rename("scala.collection.compat.**" -> "shadecompat.@1").inAll
)
assemblyMergeStrategy in assembly := {
   
   
  case PathList("META-INF", xs @ _*) => MergeStrategy.discard
  case x => MergeStrategy.first
}

之后在终端执行sbt compile, 在target/scala-2.12/src_managed/main/person_entity路径下即可生成由scalapb生成的scala文件。如果sbt compile报错 not found: value PersonEntity之类,可以尝试将由protoc生成的java文件移至src/main/scala目录下。

4. 准备数据文件

在这里,以本地目录模拟HDFS目录。以下代码将在/tmp/persons目录下生成6个文件。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值