1. 准备

Hudi支持Spark-2.x版本,你可以点击如下链接安装Spark,并使用pyspark启动

# pyspark
export PYSPARK_PYTHON=$(which python3)
spark-2.4.4-bin-hadoop2.7/bin/pyspark \
--packages org.apache.hudi:hudi-spark-bundle_2.11:0.5.1-incubating,org.apache.spark:spark-avro_2.11:2.4.4 \
--conf 'spark.serializer=org.apache.spark.serializer.KryoSerializer'
  • spark-avro模块需要在--packages显示指定
  • spark-avro和spark的版本必须匹配
  • 本示例中,由于依赖spark-avro_2.11,因此使用的是scala2.11构建hudi-spark-bundle,如果使用spark-avro_2.12,相应的需要使用hudi-spark-bundle_2.12

进行一些前置变量初始化

# pyspark
tableName = "hudi_trips_cow"
basePath = "file:///tmp/hudi_trips_cow"
dataGen = sc._jvm.org.apache.hudi.QuickstartUtils.DataGenerator()

其中DataGenerator可以用来基于行程schema生成插入和删除的样例数据。

2. 插入数据

生成一些新的行程数据,加载到DataFrame中,并将DataFrame写入Hudi表

# pyspark
inserts = sc._jvm.org.apache.hudi.QuickstartUtils.convertToStringList(dataGen.generateInserts(10))
df = spark.read.json(spark.sparkContext.parallelize(inserts, 2)) hudi_options = {
'hoodie.table.name': tableName,
'hoodie.datasource.write.recordkey.field': 'uuid',
'hoodie.datasource.write.partitionpath.field': 'partitionpath',
'hoodie.datasource.write.table.name': tableName,
'hoodie.datasource.write.operation': 'insert',
'hoodie.datasource.write.precombine.field': 'ts',
'hoodie.upsert.shuffle.parallelism': 2,
'hoodie.insert.shuffle.parallelism': 2
} df.write.format("hudi"). \
options(**hudi_options). \
mode("overwrite"). \
save(basePath)

mode(Overwrite)会覆盖并重新创建数据集。示例中提供了一个主键 (schema中的uuid),分区字段(region/county/city)和组合字段(schema中的ts) 以确保行程记录在每个分区中都是唯一的。

3. 查询数据

将数据加载至DataFrame

# pyspark
tripsSnapshotDF = spark. \
read. \
format("hudi"). \
load(basePath + "/*/*/*/*") tripsSnapshotDF.createOrReplaceTempView("hudi_trips_snapshot") spark.sql("select fare, begin_lon, begin_lat, ts from hudi_trips_snapshot where fare > 20.0").show()
spark.sql("select _hoodie_commit_time, _hoodie_record_key, _hoodie_partition_path, rider, driver, fare from hudi_trips_snapshot").show()

该查询提供读取优化视图,由于我们的分区路径格式为region/country/city),从基本路径(basepath)开始,我们使用load(basePath + "/*/*/*/*")来加载数据。

4. 更新数据

与插入新数据类似,还是使用DataGenerator生成更新数据,然后使用DataFrame写入Hudi表。

# pyspark
updates = sc._jvm.org.apache.hudi.QuickstartUtils.convertToStringList(dataGen.generateUpdates(10))
df = spark.read.json(spark.sparkContext.parallelize(updates, 2))
df.write.format("hudi"). \
options(**hudi_options). \
mode("append"). \
save(basePath)

注意,现在保存模式现在为append。通常,除非是第一次尝试创建数据集,否则请始终使用追加模式。每个写操作都会生成一个新的由时间戳表示的commit

5. 增量查询

Hudi提供了增量拉取的能力,即可以拉取从指定commit时间之后的变更,如不指定结束时间,那么将会拉取最新的变更。

# pyspark
# reload data
spark. \
read. \
format("hudi"). \
load(basePath + "/*/*/*/*"). \
createOrReplaceTempView("hudi_trips_snapshot") commits = list(map(lambda row: row[0], spark.sql("select distinct(_hoodie_commit_time) as commitTime from hudi_trips_snapshot order by commitTime").limit(50).collect()))
beginTime = commits[len(commits) - 2] # commit time we are interested in # incrementally query data
incremental_read_options = {
'hoodie.datasource.query.type': 'incremental',
'hoodie.datasource.read.begin.instanttime': beginTime,
} tripsIncrementalDF = spark.read.format("hudi"). \
options(**incremental_read_options). \
load(basePath)
tripsIncrementalDF.createOrReplaceTempView("hudi_trips_incremental") spark.sql("select `_hoodie_commit_time`, fare, begin_lon, begin_lat, ts from hudi_trips_incremental where fare > 20.0").show()

这表示查询在开始时间提交之后的所有变更,此增量拉取功能可以在批量数据上构建流式管道。

6. 特定时间点查询

即如何查询特定时间的数据,可以通过将结束时间指向特定的提交时间,将开始时间指向”000”(表示最早的提交时间)来表示特定时间。

# pyspark
beginTime = "000" # Represents all commits > this time.
endTime = commits[len(commits) - 2] # query point in time data
point_in_time_read_options = {
'hoodie.datasource.query.type': 'incremental',
'hoodie.datasource.read.end.instanttime': endTime,
'hoodie.datasource.read.begin.instanttime': beginTime
} tripsPointInTimeDF = spark.read.format("hudi"). \
options(**point_in_time_read_options). \
load(basePath) tripsPointInTimeDF.createOrReplaceTempView("hudi_trips_point_in_time")
spark.sql("select `_hoodie_commit_time`, fare, begin_lon, begin_lat, ts from hudi_trips_point_in_time where fare > 20.0").show()

7. 删除数据

删除传入的HoodieKey集合,注意:删除操作只支持append模式

# pyspark
# fetch total records count
spark.sql("select uuid, partitionPath from hudi_trips_snapshot").count()
# fetch two records to be deleted
ds = spark.sql("select uuid, partitionPath from hudi_trips_snapshot").limit(2) # issue deletes
hudi_delete_options = {
'hoodie.table.name': tableName,
'hoodie.datasource.write.recordkey.field': 'uuid',
'hoodie.datasource.write.partitionpath.field': 'partitionpath',
'hoodie.datasource.write.table.name': tableName,
'hoodie.datasource.write.operation': 'delete',
'hoodie.datasource.write.precombine.field': 'ts',
'hoodie.upsert.shuffle.parallelism': 2,
'hoodie.insert.shuffle.parallelism': 2
} from pyspark.sql.functions import lit
deletes = list(map(lambda row: (row[0], row[1]), ds.collect()))
df = spark.sparkContext.parallelize(deletes).toDF(['partitionpath', 'uuid']).withColumn('ts', lit(0.0))
df.write.format("hudi"). \
options(**hudi_delete_options). \
mode("append"). \
save(basePath) # run the same read query as above.
roAfterDeleteViewDF = spark. \
read. \
format("hudi"). \
load(basePath + "/*/*/*/*")
roAfterDeleteViewDF.registerTempTable("hudi_trips_snapshot")
# fetch should return (total - 2) records
spark.sql("select uuid, partitionPath from hudi_trips_snapshot").count()

8. 总结

本篇博文展示了如何使用pyspark来插入、删除、更新Hudi表,有pyspark和Hudi需求的小伙伴不妨一试!

真香!PySpark整合Apache Hudi实战的更多相关文章

  1. 实战 | 将Apache Hudi数据集写入阿里云OSS

    1. 引入 云上对象存储的廉价让不少公司将其作为主要的存储方案,而Hudi作为数据湖解决方案,支持对象存储也是必不可少.之前AWS EMR已经内置集成Hudi,也意味着可以在S3上无缝使用Hudi.当 ...

  2. 实战| 配置DataDog监控Apache Hudi应用指标

    1. 可用性 在Hudi最新master分支,由Hudi活跃贡献者Raymond Xu贡献了DataDog监控Hudi应用指标,该功能将在0.6.0 版本发布,也感谢Raymond的投稿. 2. 简介 ...

  3. Apache Hudi + AWS S3 + Athena实战

    Apache Hudi在阿里巴巴集团.EMIS Health,LinkNovate,Tathastu.AI,腾讯,Uber内使用,并且由Amazon AWS EMR和Google云平台支持,最近Ama ...

  4. 阿里神器 Seata 实现 TCC模式 解决分布式事务,真香!

    今天这篇文章介绍一下Seata如何实现TCC事务模式,文章目录如下: 什么是TCC模式? TCC(Try Confirm Cancel)方案是一种应用层面侵入业务的两阶段提交.是目前最火的一种柔性事务 ...

  5. Apache Beam实战指南 | 手把手教你玩转KafkaIO与Flink

    https://mp.weixin.qq.com/s?__biz=MzU1NDA4NjU2MA==&mid=2247492538&idx=2&sn=9a2bd9fe2d7fd6 ...

  6. 《Apache kafka实战》读书笔记-kafka集群监控工具

    <Apache kafka实战>读书笔记-kafka集群监控工具 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 如官网所述,Kafka使用基于yammer metric ...

  7. SpringBoot与Shiro整合权限管理实战

    SpringBoot与Shiro整合权限管理实战 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] *观看本文章需要有一定SpringBoot整合经验* Shiro框架简介 Apach ...

  8. 使用Apache Hudi构建大规模、事务性数据湖

    一个近期由Hudi PMC & Uber Senior Engineering Manager Nishith Agarwal分享的Talk 关于Nishith Agarwal更详细的介绍,主 ...

  9. Apache Hudi和Presto的前世今生

    一篇由Apache Hudi PMC Bhavani Sudha Saktheeswaran和AWS Presto团队工程师Brandon Scheller分享Apache Hudi和Presto集成 ...

随机推荐

  1. 从3dMax导出供threeJS使用的带动作模型与加载

    评论区发现的建议,最近没空测试,先贴这 还有好多人说找不到插件的 https://pan.baidu.com/s/1Q5g0... 密码:b43e . 应该是他们现在只是维护blender,只有这个的 ...

  2. 如何在Ubuntu 18.04上安装Nginx

    Nginx功能之强大,想必大家比我更清楚. 百度百科:Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务.Nginx是由伊戈尔 ...

  3. .NET 4 实践 - 使用dynamic和MEF实现轻量级的AOP组件 (4)

    转摘 https://www.cnblogs.com/niceWk/archive/2010/07/23/1783394.html 借花献佛 前面我们介绍了构成DynamicAspect绝大部分的类, ...

  4. 树莓派4b 上手三板斧

    树莓派4b 上手三板斧 1.无屏幕和网线连接准备 windows / mac 电脑下载安装Notepad++ 新建文件并保存为ssh(该文件为空文件) 新建文件wpa_supplicant.conf ...

  5. SpringCloud-Config 配置中心

    概述 分布式系统面临的问题 微服务意味着要将单体应用中的业务拆分成一个个的子服务,这些服务都需要必要的配置信息才能运行,如果有上百个微服务,上百个配置文件,管理起来是非常困难的,这时候,一套集中式的. ...

  6. 开发机直连 Docker 中的 Redis 容器小教程

    在笔者日常开发中,都是把redis装在windows系统中.虽然可以通过RedisDesktopManager等客户端工具连接操作redis,但是还是觉得low了一些.因为作为程序员,我可能更想在Li ...

  7. 【转帖】Python 重复造轮子/造轮子找模子,你都应该熟读该文

    Chardet,字符编码探测器,可以自动检测文本.网页.xml的编码. colorama,主要用来给文本添加各种颜色,并且非常简单易用. Prettytable,主要用于在终端或浏览器端构建格式化的输 ...

  8. Linux系统管理第四次作业 磁盘管理 文件系统

    1.为主机新增两块30GB的SCSI硬盘 2.划分3个主分区,各5GB,剩余空间作为扩展分区 [root@localhost ~]# fdisk /dev/sdb 欢迎使用 fdisk (util-l ...

  9. Ali_Cloud++:阿里云服务器部署【禅道】项目管理系统

    1.开源版安装包下载 地址一:百度云下载 10.0  提取码:2dyg  地址二:官方下载 2.直接解压安装包到/opt目录下 注意:这里我安装的是Linux一键安装包官方给出的方法就是直接解压到/o ...

  10. 【Linux网络基础】网络子网划分基础知识(IP地址,子网)

    一. IP地址分类与子网划分基础 1. 什么是IP地址? 常见的ip地址版本为ipv4, ipv6 32位 4 * 8=32位. 32位二进制数字序列组成的数字序列   点分十进制 采用点将32位数字 ...