重磅!Vertica整合Apache Hudi指南

leesf發表於2022-03-29

1. 摘要

本文演示了使用外部表整合 Vertica 和 Apache Hudi。 在演示中我們使用 Spark 上的 Apache Hudi 將資料攝取到 S3 中,並使用 Vertica 外部表訪問這些資料。

2. Apache Hudi介紹

Apache Hudi 是一種變更資料捕獲 (CDC) 工具,可在不同時間線將事務記錄在表中。 Hudi 代表 Hadoop Upserts Deletes and Incrementals,是一個開源框架。 Hudi 提供 ACID 事務、可擴充套件的後設資料處理,並統一流和批處理資料處理。
以下流程圖說明了該過程。 使用安裝在 Apache Spark 上的 Hudi 將資料處理到 S3,並從 Vertica 外部表中讀取 S3 中的資料更改。

3. 環境準備

  • Apache Spark 環境。 使用具有 1 個 Master 和 3 個 Worker 的 4 節點叢集進行了測試。 按照在多節點叢集上設定 Apache Spark 中的說明安裝 Spark 叢集環境。 啟動 Spark 多節點叢集。
  • Vertica 分析資料庫。 使用 Vertica Enterprise 11.0.0 進行了測試。
  • AWS S3 或 S3 相容物件儲存。 使用 MinIO 作為 S3 儲存桶進行了測試。
  • 需要以下 jar 檔案。將 jar 複製到 Spark 機器上任何需要的位置,將這些 jar 檔案放在 /opt/spark/jars 中。
    • Hadoop - hadoop-aws-2.7.3.jar
    • AWS - aws-java-sdk-1.7.4.jar
  • 在 Vertica 資料庫中執行以下命令來設定訪問儲存桶的 S3 引數:
SELECT SET_CONFIG_PARAMETER('AWSAuth', 'accesskey:secretkey');
SELECT SET_CONFIG_PARAMETER('AWSRegion','us-east-1');
SELECT SET_CONFIG_PARAMETER('AWSEndpoint',’<S3_IP>:9000');
SELECT SET_CONFIG_PARAMETER('AWSEnableHttps','0');

endpoint可能會有所不同,具體取決於 S3 儲存桶位置選擇的 S3 物件儲存。

4. Vertica和Apache Hudi整合

要將 Vertica 與 Apache Hudi 整合,首先需要將 Apache Spark 與 Apache Hudi 整合,配置 jars,以及訪問 AWS S3 的連線。 其次,將 Vertica 連線到 Apache Hudi。 然後對 S3 儲存桶執行 Insert、Append、Update 等操作。
按照以下部分中的步驟將資料寫入 Vertica。
在 Apache Spark 上配置 Apache Hudi 和 AWS S3
配置 Vertica 和 Apache Hudi 整合

4.1 在 Apache Spark 上配置 Apache Hudi 和 AWS S3

在 Apache Spark 機器中執行以下命令。
這會下載 Apache Hudi 包,配置 jar 檔案,以及 AWS S3

/opt/spark/bin/spark-shell \
--conf "spark.serializer=org.apache.spark.serializer.KryoSerializer"\--packages org.apache.hudi:hudi-spark3-bundle_2.12:0.9.0,org.apache.spark:spark-avro_2.12:3.0.1

匯入Hudi的讀、寫等所需的包:

import org.apache.hudi.QuickstartUtils._
import scala.collection.JavaConversions._
import org.apache.spark.sql.SaveMode._
import org.apache.hudi.DataSourceReadOptions._
import org.apache.hudi.DataSourceWriteOptions._
import org.apache.hudi.config.HoodieWriteConfig._

使用以下命令根據需要配置 Minio 訪問金鑰、Secret key、Endpoint 和其他 S3A 演算法和路徑。

spark.sparkContext.hadoopConfiguration.set("fs.s3a.access.key", "*****")
spark.sparkContext.hadoopConfiguration.set("fs.s3a.secret.key", "*****")
spark.sparkContext.hadoopConfiguration.set("fs.s3a.endpoint", "http://XXXX.9000")
spark.sparkContext.hadoopConfiguration.set("fs.s3a.path.style.access", "true")
sc.hadoopConfiguration.set("fs.s3a.signing-algorithm","S3SignerType")

建立變數來儲存 MinIO 的表名和 S3 路徑。

val tableName = “Trips”
val basepath = “s3a://apachehudi/vertica/”

準備資料,使用 Scala 在 Apache spark 中建立示例資料

val df = Seq(
("aaa","r1","d1",10,"US","20211001"),
("bbb","r2","d2",20,"Europe","20211002"),
("ccc","r3","d3",30,"India","20211003"),
("ddd","r4","d4",40,"Europe","20211004"),
("eee","r5","d5",50,"India","20211005"),
).toDF("uuid", "rider", "driver","fare","partitionpath","ts")

將資料寫入 AWS S3 並驗證此資料

df.write.format("org.apache.hudi").
options(getQuickstartWriteConfigs).
option(PRECOMBINE_FIELD_OPT_KEY, "ts").
option(RECORDKEY_FIELD_OPT_KEY, "uuid").
option(PARTITIONPATH_FIELD_OPT_KEY, "partitionpath").
option(TABLE_NAME, tableName).
mode(Overwrite).
save(basePath)

使用 Scala 執行以下命令以驗證是否從 S3 儲存桶中正確讀取資料。

spark.read.format("hudi").load(basePath).createOrReplaceTempView("dta")
spark.sql("select _hoodie_commit_time, uuid, rider, driver, fare,ts, partitionpath from  dta order by uuid").show()

4.2 配置 Vertica 和 Apache HUDI 整合

在 vertica 中建立一個外部表,其中包含來自 S3 上 Hudi 表的資料。 我們建立了“旅行”表。

CREATE EXTERNAL TABLE Trips
(
_hoodie_commit_time TimestampTz,
uuid varchar,
rider varchar,
driver varchar,
fare int,
ts varchar,
partitionpath varchar
)
AS COPY FROM
's3a://apachehudi/parquet/vertica/*/*.parquet' PARQUET;

執行以下命令以驗證正在讀取外部表:

4.3 如何讓 Vertica 檢視更改的資料

以下部分包含為檢視 Vertica 中更改的資料而執行的一些操作的示例。

4.3.1 寫入資料

在這個例子中,我們使用 Scala 在 Apache spark 中執行了以下命令並附加了一些資料:

val df2 = Seq(
("fff","r6","d6",50,"India","20211005")
).toDF("uuid", "rider", "driver","fare","partitionpath","ts")

執行以下命令將此資料附加到 S3 上的 Hudi 表中:

df2.write.format("org.apache.hudi").
options(getQuickstartWriteConfigs).
option(PRECOMBINE_FIELD_OPT_KEY, "ts").
option(RECORDKEY_FIELD_OPT_KEY, "uuid").
option(PARTITIONPATH_FIELD_OPT_KEY, "partitionpath").
option(TABLE_NAME, tableName).
mode(Append).
save(basePath)

4.3.2 更新資料

在這個例子中,我們更新了一條 Hudi 表的記錄。 需要匯入資料以觸發並更新資料:

val df3 = Seq(
("aaa","r1","d1",100,"US","20211001"),
("eee","r5","d5",500,"India","20211001")
).toDF("uuid", "rider", "driver","fare","partitionpath","ts")

執行以下命令將資料更新到 S3 上的 HUDI 表:

df3.write.format("org.apache.hudi").
options(getQuickstartWriteConfigs).
option(PRECOMBINE_FIELD_OPT_KEY, "ts").
option(RECORDKEY_FIELD_OPT_KEY, "uuid").
option(PARTITIONPATH_FIELD_OPT_KEY, "partitionpath").
option(TABLE_NAME, tableName).
mode(Append).
save(basePath)

以下是 spark.sql 的輸出:

以下是 Vertica 輸出:

4.3.3 建立和檢視資料的歷史快照

執行以下指向特定時間戳的 spark 命令:

val dd = spark.read
.format("hudi")
.option("as.of.instant", "20211007092600")
.load(basePath)				

使用以下命令將資料寫入 S3 中的 parquet:

dd.write.parquet("s3a://apachehudi/parquet/p2")

在此示例中,我們正在讀取截至“20211007092600”日期的 Hudi 錶快照。

dd.show

通過在 parquet 檔案上建立外部表從 Vertica 執行命令。

相關文章