数据湖架构--Iceberg

和Hudi类似,Iceberg也提供了数据湖的功能,根据官网的定义,它是一个为分析大数据集开源的表存储格式,可以SQL表一样用Spark、Preso进行查询。Iceberg框架很好的解耦了数据计算与数据存储,计算引擎支持Spark、Flink和Hive等。本文第一部分将用Spark进行数据操作,后续再补充Flink操作部分。

功能特性

  1. 支持Schema变更:字段的增删改对数据表没有影响
  2. Hidden Partition:用户不用再去管理表的partition,在Hive中插入数据时是需要指定partition的,因为Hive并不会检查分区格式,所以用户要自己去校验分区格式是否正确,在Iceberg中,系统会自动处理数据并保存到正确的分区中。

Schema管理

Iceberg Schema可以通过HiveMetastore方式或者Hadoop文件方式进行管理,两种方式在处理Metadata的文件名时采用不同的方式,如果想直接通过Hive指定外部表是不行的。这种处理方式有些奇怪,不知道是不是因为我还没有看到这个设计背后的原因。

  • hadoop文件,查看文件命名规则
  • hive metastore元数据管理,Iceberg表以外部表的形式存储在hive metastore中,

表以及数据操作

下面会通过Spark操作Iceberg的表和数据相关的怎删改操作,为了能够识别Iceberg,首先要启动SparkSession并配置好Iceberg的参数,参数是Metastore的位置,通过设置spark.sql.catalog.spark_catalog.type 来确定使用Hadoop文件还是Hive metastore,因为之后要使用Presto,这里用HiveMetastore来管理Iceberg的Metadata

  val spark = SparkSession.builder().appName("aaa").
    master("local[1]").
    config("spark.sql.catalog.spark_catalog","org.apache.iceberg.spark.SparkSessionCatalog").
    //使用Hive Metastore管理元数据
    config("spark.sql.catalog.spark_catalog.type","hive").
    config("spark.sql.catalog.hadoop_prod", "org.apache.iceberg.spark.SparkCatalog").
    config("spark.sql.catalog.hadoop_prod.type", "hadoop").
    config("spark.sql.catalog.hadoop_prod.warehouse", "hdfs://10.91.88.1:9000/tmp/iceberg").
    config("spark.sql.catalog.hive_prod","org.apache.iceberg.spark.SparkCatalog").
    config("spark.sql.catalog.hive_prod.type","hive").
    config("spark.sql.catalog.hive_prod.uri", "thrift://10.91.88.1:9083").
    getOrCreate()

表历史

查看历史快照

spark.sql(
    s"""select * from $catalog.$dbTableName.snapshots
      |""".stripMargin).show(false)
spark.sql(
    s"""select * from $catalog.$dbTableName.history
       |""".stripMargin).show(false)

创建表

Spark SQL创建表,并添加数据

  spark.sql(
    """create table hive_prod.bbb.test (username string) using iceberg
      |""".stripMargin)
  spark.sql(
    """insert into hive_prod.bbb.test values ("user1"),("user2"),("user3")
      |""".stripMargin)
  spark.sql(
    """select * from hive_prod.bbb.test
      |""".stripMargin).show(false)

添加字段

添加字段成功之后,通过hive-cli可以验证新添加的字段

  spark.sql(
    """alter table hive_prod.bbb.test add column address string, gender string
      |""".stripMargin)

删除字段

spark.sql("alter table hive_prod.bbb.test drop column city")

Presto 查询

在Presto Server中添加Iceberg配置,/usr/lib/presto/etc/catalog/iceberg.properties

connector.name=iceberg
hive.metastore.uri=thrift://10.91.88.1:9083

回退以及历史查询

查看表的Snapshot历史信息,Iceberg支持时间旅行,即历史查询,SparkSQL目前不支持TimeTravel,需要用Spark API进行调用。

spark.read
    .option("snapshot-id", 10963874102873L)
    .format("iceberg")
    .load("path/to/table")

恢复到历史版本,需要同JavaAPI实现

val conf = new Configuration()
val warehousePath = "hdfs://10.91.88.1:9000/tmp/iceberg"
val catalog1 = new HadoopCatalog(conf, warehousePath)
val table = catalog1.loadTable(TableIdentifier.of("bbb", "test3"))
val sid = 4125943832602474030L
table.manageSnapshots().rollbackTo(sid).commit()

小文件合并

Iceberg合并小文件时并不会删除被合并的文件,Compact是将小文件合并成大文件并创建新的Snapshot。如果要删除文件需要通过Expire Snapshots来实现

Configuration conf = new Configuration();
String warehousePath = "hdfs://10.91.88.1:9000/tmp/iceberg";
HadoopCatalog catalog1 = new HadoopCatalog(conf, warehousePath);
Table table = catalog1.loadTable(TableIdentifier.of("bbb", "test8"));
Actions.forTable(table)
        .rewriteDataFiles()
        .targetSizeInBytes(100 * 1024 * 1024) // 100 MB
        .execute();

删除历史快照

历史快照是通过ExpireSnapshot来实现的,设置需要删除多久的历史快照

long tsToExpire = System.currentTimeMillis() - (1000*60*30 ); 
table.expireSnapshots()
        .expireOlderThan(tsToExpire)
        .commit();

你可能感兴趣的:(数据湖架构--Iceberg)