数据湖架构--DeltaLake

DeltaLake是一个开源的存储层,它为大数据的读写带来了ACID的能力,通过快照隔离机制为HDFS提供了读写一致性的保证,同时DeltaLake提供内部版本的跟踪更能,使得用户可以轻松进行快照、版本回滚。
数据湖是近些年提出的新的数据架构,将大量的数据存储到数据湖中,数据湖可以认为是一个可以无限扩展的存储和计算架构。然而在数据湖实践落地的过程中也存在以下问题

  1. 数据质量问题,数据进入数据湖由于没有任何数据格式校验过程,所以经常出现数据值缺失或者数据错误的情况
  2. 数据稳定性问题,与传统关系性数据库相比,大数据缺少事务管理特性,所以会出现数据不一致的情况,通常要进行数据的重新处理
  3. 性能问题,随着数据湖中数据的不断增加,文件和目录的数量也会大量的增加,数据作业在处理元数据上实践花费的实践越来越多,性能越来越差
  4. 数据更新问题,现在的数据仓库存储结构主要是基于分区级别更新的,不支持更细颗粒度的更新

DeltaLake架构提供的功能可以很好的解决目前数据湖存储架构的问题

  1. ACID,支持强级别的隔离机制保证数据的一致性,每次写入都同时都会添加一个新的数据文件,并为这次写入添加一个log文件,Log文件会记录这次数据的变更,这样做的目的可以保证数据变更的原子性,读写操作保持独立。
  2. 可扩展的元数据管理,元数据以文件的形式进行管理,元数据处理方式同数据文件一样处理,因此通过分布式的处理方式,可以轻松管理上百万个分区
  3. 流批一体,支持流批一体的处理方式,通过一套代码对批流进行同意处理,避免了同逻辑两套代码的重复成本投入
  4. Schema管理,支持Schema的进化和变化管理,支持增减字段
  5. 数据修改,支持行级别的merge、upsert和delete操作,同是也支持一些复杂的予以处理比如CDC
spark shell

通过spark直接操作delta

bin/spark-shell --packages io.delta:delta-core_2.12:0.7.0 \
--conf "spark.sql.extensions=io.delta.sql.DeltaSparkSessionExtension" \
--conf "spark.sql.catalog.spark_catalog=org.apache.spark.sql.delta.catalog.DeltaCatalog"
创建表

通过Spark API创建表

val df = spark.range(10)
df.write.format("delta").mode(SaveMode.Overwrite).save("file:///tmp/delta/testdata")

通过Sql创建表,Spark需要打开HiveSupport开关

spark.sql("create table testdata (id int) using delta")
spark.sql("insert into testdata values (1),(2),(3),(4)")
更新数据

通过Spark API更新数据

val table = DeltaTable.forPath("/tmp/delta/testdata")      table.update(col("id").equalTo(1), Map("id"-> lit("100")))

通过Sql更新数据

spark.sql("update testdata set id=100 where id=1")
删除数据

通过Spark API删除数据

val table = DeltaTable.forPath("/tmp/delta/testdata")
table.delete(col("id").equalTo(100))

通过Sql删除数据

spark.sql("delete from testdata where id=100")
字段增加

通过SparkAPI进行merge时,updateAll和insertAll会自动添加字段,insert/update是可以的,自动更新需要添加一个Spark的配置"spark.databricks.delta.schema.autoMerge.enabled"=true

val newData = spark.createDataFrame(spark.sparkContext.parallelize(Seq((2, "SH"), (30, "ZD"))))
      .toDF("id", "city")
    table.as("old").merge(
      newData.as("new"),
      "new.id==old.id")
      .whenMatched
      .updateAll()
      .whenNotMatched()
      .insertAll()
      .execute()

SQL添加字段

spark.sql("alter table testdata add columns (city string)")
字段修改删除

Deltalake只支持字段的备注和顺序的修改,修改字段类型或者删除字段需要重刷数据。

alter table testdata change city city string comment 'city' first"

Kafka流式数据处理

从kafka topic中读取数据保存到Delta Lake中

 val df = spark.readStream.format("kafka")
    .option("kafka.bootstrap.servers", "a80.kd:9092")
    .option("subscribe", "updates")
    .load()


  import spark.implicits._
  val schema = new StructType()
    .add($"uid".int)
    .add($"email".string)
  val output = df.selectExpr("CAST(key AS STRING)", "CAST(value AS STRING)").as[(String, String)]
    .select(from_json(col("value"), schema).alias("dd"))
    .select("dd.uid", "dd.email")
    .writeStream
    .format("delta")
    .outputMode("append")
    .option("checkpointLocation", "file:///tmp/delta/events/_checkpoints/etl-from-json")
    .start("file:///tmp/delta/events")
    output.awaitTermination()
表历史

显示表历史记录

  val table = DeltaTable.forPath("/tmp/delta/events")
  table.history().show()

时间旅行,查看历史中某个版本的记录

  val df = spark.read.format("delta").option("versionAsOf", 0).load("/tmp/delta/events")
  df.show()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值