数据湖是用来存储什么样的数据呢?
数据湖是以什么样的存储模式存储数据呢?是关系型数据库的模式吗?
数据湖与Delta Lake的关系是?
数据湖可以替代数据仓库吗?
简单对比下数据湖与数据仓库。
数据湖存储起来非常方便,为了保证敏捷开发,是无需管理的,对吗?
Apache Hudi是干什么的?仅仅实现增删改查吗?
基于Hudi的数据湖数据是以什么方式存储的?
Hudi有元数据吗?元数据存储在哪儿?
Hudi是以什么方式与Spark进行整合的?
1
从数据仓库到数据湖
1
仓库和湖泊
仓库是人为提前建造好的,有货架,还有过道,并且还可以进一步为放置到货架的物品指定位置。
而湖泊是液态的,是不断变化的、没有固定形态的,基本上是没有结构的,湖泊可以是由河流 、小溪和其他未被任何处理的水源维持。湖泊是不需要预先指定结构的。
2
什么是数据湖?
数据湖(Data Lake)和数据库、数据仓库一样,都是数据存储的设计模式。数据库和数据仓库会以关系型的方式来设计存储、处理数据。但数据湖的设计理念是相反的,数据仓库是为了保障数据的质量、数据的一致性、数据的重用性等对数据进行结构化处理。
数据湖是一个数据存储库,可以使用数据湖来存储大量的原始数据。现在企业的数据仓库都会通过分层的方式将数据存储在文件夹、文件中,而数据湖使用的是平面架构来存储数据。我们需要做的只是给每个数据元素分配一个唯一的标识符,并通过元数据标签来进行标注。当企业中出现业务问题时,可以从数据湖中查询数据,然后分析业务对应的那一小部分数据集来解决业务问题。
了解过Hadoop的同学知道,基于Hadoop可以存储任意形式的数据。所以,很多时候数据湖会和Hadoop关联到一起。例如:把数据加载Hadoop中,然后将数据分析、和数据挖掘的工具基于Hadoop进行处理。数据湖越来越多的用于描述任何的大型数据池,数据都是以原始数据方式存储,知道需要查询应用数据的时候才会开始分析数据需求和应用架构。
数据湖是描述数据存储策略的方式,并不与具体的某个技术框架关联。数据库、数据仓库也一样。它们都是数据的管理策略。
数据湖是专注于原始数据保真以及低成本长期存储的存储设计模式,它相当于是对数据仓库的补充。数据湖是用于长期存储数据容器的集合,通过数据湖可以大规模的捕获、加工、探索任何形式的原始数据。通过使用一些低成本的技术,可以让下游设施可以更好地利用,下游设施包括像数据集市、数据仓库或者是机器学习模型。
3
数据湖的优点
提供不限数据类型的存储
开发人员和数据科学家可以快速动态建立数据模型、构建应用、查询数据,非常灵活。
因为数据湖没有固定的结构,所以更易于访问
长期存储数据的成本低廉,数据湖可以安装在低成本的硬件在,例如:
在一般的X86机器上部署Hadoop
因为数据湖是非常灵活的,它允许使用多种不同的处理、分析方式来让数据发挥价值,例如:
数据分析、实时分析、机器学习以及SQL查询都可以。
4
Data Lake VS Data warehouse
数据湖和数据仓库是用于存储大数据的两种不同策略,最大区别是:数据仓库是提前设计好模式(schema)的,因为数据仓库中存储的都是结构化数据。而在数据湖中,不一定是这样的。数据湖中可以存储结构化和非结构化的数据,是无法预先定义好结构的。
我们来进一步进行对比:
数据的存储位置不同
数据仓库因为是要有结构的,在企业中很多都是基于关系型模型。而数据湖通常位于分布式存储例如Hadoop或者类似的大数据存储中。
数据源不同
数据仓库的数据来源很多时候来自于OLTP应用的结构化数据库中提取的,用于支持内部的业务部门(例如:销售、市场、运营等部门)进行业务分析。而数据湖的数据来源可以是结构化的、也可以是非结构化的,例如:业务系统数据库、 IOT设备、社交媒体、移动APP等。
用户不同
数据仓库主要是业务系统的大量业务数据进行统计分析,所以会应用数据分析的部门是数据仓库的主要用户,例如:销售部、市场部、运营部、总裁办等等。而当需要一个大型的存储,而当前没有明确的数据应用用户或者是目标,将来想要使用这些数据的人可以在使用时开始设计架构,此时,数据湖更适合。
但数据湖中的数据都是原始数据,是未经整理的,这对于普通的用户几乎是不可用的。数据湖更适合数据科学家,因为数据科学家可以应用模型、技术发觉数据中的价值,去解决企业中的业务问题。
数据质量
数据仓库是非常重数据质量的,大家现在经常听说的数据中台,其中有一大块是数据质量管理、数据资产管理等。数据仓库中的数据都是经过处理的。而数据湖中的数据可靠性是较差的,这些数据可能是任意状态、形态的数据。
数据模式
数据仓库在数据写入之前就要定义好模式(schema),例如:我们会先建立模型、建立表结构,然后导入数据。我们可以把它称之为write-schema。而数据湖中的数据是没有模式的,直到有用户要访问数据、使用数据才会建立schema。我们可以把它称之为read-schema。
敏捷扩展性
数据仓库的模式一旦建立,要重新调整模式,往往代价很大,牵一发而动全身,所有相关的ETL程序可能都需要调整。而数据湖是非常灵活的,可以根据需要重新配置结构或者模式。
基于上述内容,我们可以了解到,数据湖和数据仓库的应用点是不一样的。他们是两种相对独立的数据设计模式。在一些企业中,可能会既有数据湖、又有数据仓库。数据湖并不是要替代数据仓库,而是对企业的数据管理模式进行补充。
应用
数据仓库一般用于做批处理报告、BI、可视化。而数据湖主要用于机器学习、预测分析、数据探索和分析。
5
数据湖应用
数据湖是用于数据存储的设计模式,但最终数据肯定是需要一种介质存储下来的。我们可以自己来选择数据湖的物理存储引擎。例如:使用Hadoop作为数据湖的物理存储引擎、或者使用AWS的S3作为存储引擎等。
但架构数据湖时,需要注意几点原则,这几点原则也将和其他数据存储方法区别开来。
可以加载各种源系统中的数据,并存储。
任意类型的数据都可以存储。
数据是以原始状态保存在数据湖中的,是几乎不需要做任何转换的。
数据可以根据应用、分析的要求,进行转换成适合分析的模式
构建数据湖时,为了方便数据的管理。我们可以建立一些管理办法,例如:
将数据进行合理分类,例如:
按照数据类型分类、按照业务内容分类、按照应用场景分类或者按照可能的用户来分类。
为了方便数据湖的数据存取,要提前定义好命名规则和固定的文件目录结构。
如果出现数据质量问题也可以解决掉。
建立数据访问标准,可以追踪到哪些用户正在访问数据。
让数据目录可以被检索到。
提供一些加密、监控、授权、警报等功能。
6
不要让数据湖变成一潭死水
如果数据湖没有任何管理办法,不进行任何的治理,那么所有的数据将会是不可追溯的,再一大堆的数据,但杂乱不堪。数据湖将不再是数据湖,变成了一潭死水,或者泥潭,白白浪费大量有价值的数据。如果数据无人维护管理,数据湖最终变成了数据坟墓。这就尴尬了。所以,一旦建设了数据湖,一定要配有管理人员。对数据湖的治理负责。
除了具备基本的存储、敏捷可扩展特性外,一个管理良好的数据湖还应该具备以下特征:
提供方便进行访问、操作的API接口,应该Data Lake的应用场景很多,很灵活,所以应该提供方便提数的API接口
具备有访问控制机制。
可以方便数据的owner控制数据湖中数据的访问权限,并支持一些加密、网络安全等功能。
具备搜索和分类功能。
如果没法方便地进行数据湖数据的组织,以及快速检索数据,数据湖无法最大化地发挥作用。
数据湖能够提供方便进行处理和分析层,数据分析师、数据科学家、机器学习算法工程师能够集中访问。
数据湖还应该提供统一、易用的访问方式。
2
了解Apache Hudi
1
介绍
打开Hudi的官网,映入眼帘的是“Apache Hudi通过分布式文件系统——HDFS或者云存储”来摄取、管理大型分析型数据集。也就是Hudi是可以借助于HDFS之上,提供了一些提取、管理功能。
这是Hudi数据湖的基础架构。
简单解释下:
通过Kafka、Sqoop、DeltaStreammer、Flink、Spark等工作,将数据摄取到数据湖的数据存储,例如:
我们可以使用HDFS作为数据湖的数据存储
基于HDFS可以构建Hudi的数据湖
Hudi提供统一的访问Spark数据源
外部通过不同引擎,例如:
Spark、Presto、Hive、Impala、Aliyun DLA、AWS Redshit访问接口
Hudi提供的功能
支持使用索引方式Upsert
可以原子性的发布数据并支持回滚
写入和查询使用快照进行隔离,保证数据的一致性
可以用用Savepoint进行数据恢复
支持基于统计数据管理文件大小和分布
支持对基于行、列的数据进行异步压缩
支持时间轴元数据进行数据血统追踪
可以说,Hudi支持了数据湖的数据存储以及一定的管理功能。
2
Github热度对比Delta Lake
Hudi很自信地把GITHUB的Star、Fork、Watch放上了官网。
对比下Delta Lake
看Watch,我们可以知道Hudi的关注度是很高的。再对比一下PR、和commit。
Hudi
Delta Lake
大家感受一下吧。
3
快速体验Hudi
Hudi是基于Spark的2.x版本,出于开发简单性考虑,本次我将基于Hadoop,用IDEA来开发Hudi的入门示例。因为是基于Hudi构建数据湖,所以,我们先准备数据存入到Hudi中,然后再进行查询,全程基于Spark SQL来操作。
版本信息:
Spark 2.4.7
Scala 2.12
Hudi 0.6.0
Hadoop 2.7.5
1
导入Maven依赖
2.4.7
2.12
2.7.5
0.6.0
org.apache.spark
spark-core_${scala-version}
${spark-version}
org.apache.spark
spark-sql_${scala-version}
${spark-version}
org.apache.commons
commons-lang3
3.1
org.apache.hadoop
hadoop-client
${hadoop-version}
org.apache.hudi
hudi-spark-bundle_${scala-version}
${hudi-version}
org.apache.httpcomponents
httpclient
4.5.11
org.apache.spark
spark-avro_${scala-version}
${spark-version}
src/main/scala
2
编写写入数据实现
/**
* 出于简单,此处使用一个用户访问日志WebLog作为测试数据
* @param ip IP地址
* @param id 每次访问的唯一ID
* @param url 用户访问的URL
* @param date 访问日期
*/
case class WebLog(ip:String, id:String, url:String, date:String)
object SparkHudiFirst {
def main(args: Array[String]): Unit = {
// 创建SparkSQL执行环境
val spark = SparkSession
.builder()
.master("local[*]")
.config("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
.config("spark.default.parallelism", 4)
.appName("Spark Hudi Load")
.getOrCreate()
// 构建元数据
val tableName = "hudi_weblog"
val hdfsPath = "/datalake/test/hudi_first"
// 基于内存测试数据构建DataFrame
// 生成10000条测试数据
val MAX_DATA_NUM = 10000
val r = new Random()
val logList = (1 to MAX_DATA_NUM)
.map(n => {
val ip = (1 to 4)
.map(x => (r.nextInt(255) + 1) % 255)
.toList
.mkString(".")
val id = UUID.randomUUID().toString
val url = s"/pro/goods/${RandomStringUtils.randomAlphanumeric(10)}.html"
val date = s"2021-${(r.nextInt(13) + 1) % 13}-${(r.nextInt(32) + 1) % 32}"
WebLog(ip, id, url, date)
})
import spark.implicits._
val weblogDF = spark
.createDataFrame(logList)
.select($"ip"
, $"id"
, $"url"
, $"date"
, $"date"
.substr(0, 4)
.as("year"))
weblogDF
.write
.format("hudi")
.options(getQuickstartWriteConfigs)
.option(PRECOMBINE_FIELD_OPT_KEY, "date")
.option(RECORDKEY_FIELD_OPT_KEY, "id")
.option(PARTITIONPATH_FIELD_OPT_KEY, "year")
.option(TABLE_NAME, tableName)
.mode(Overwrite)
.save(hdfsPath)
}
}
程序执行完后,我们在HDFS中可以看到数据文件已经生成好了
我们可以看到,数据是以parquet文件保存的。并且除了数据文件之外,还有Hudi自动生成的用于保存元数据的文件夹。
3
查询数据
object HudiQueryData {
def main(args: Array[String]): Unit = {
// 创建SparkSQL执行环境
val spark = SparkSession
.builder()
.master("local[*]")
.config("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
.config("spark.default.parallelism", 4)
.appName("Spark Hudi Query")
.getOrCreate()
// 构建元数据
val tableName = "hudi_weblog"
val hdfsPath = "/datalake/test/hudi_first"
// 基于Hudi创建DF
val weblogDF = spark
.read
.format("hudi")
.load(hdfsPath + "/2021")
// Spark SQL创建临时表
weblogDF.createOrReplaceTempView(tableName)
// 执行SQL查询
spark.sql(s"""
| select
| *
| from
| ${tableName}
""".stripMargin)
.show(20)
}
}
我们发现基于Hudi我们已经把数据都查询出来了,并且Hudi帮助我们添加了元数据。
此处只是做了一个非常简单的Hudi入门体验,下一次我将推出更多关于Hudi的内容。关注我吧!
# 总结
数据湖是用来存储什么样的数据呢?
存储原始数据,结构化的非结构化的数据都可以,可以存储任意类型的数据
数据湖是以什么样的存储模式存储数据呢?
是关系型数据库的模式吗?
不是。如果仅是存储数据的话,数据湖是没有schema的。可以任意存储。
数据湖与Delta Lake的关系是?
数据湖是一种数据存储的设计模式,而Delta Lake是可以用于构建数据湖的工具。
数据湖可以替代数据仓库吗?
不可以,他们二者是可以相互补充的。
简单对比下数据湖与数据仓库。
首先他们两都是企业中的数据存储设计模式,都是概念上的。
1. 数据湖可以存储任意结构化、半结构化或者非结构的数据,而数仓只是结构化数据。
2. 数据湖中的数据可以供任意人员使用,但因数据湖中的数据都是原始数据,对人员要求会比较高。而数据仓库面向的各个需要查看BI的业务线。是整理过的数据,使用起来成本较小。
3. 数据湖设计之初可能是没有具体的目标,后续需要用到数据时随时提取。数仓设计是有非常明确的目标的。
4. 数据湖是读schema,也就是读取的时候再建立schema。而数仓必须先建立schema,再写入。
5. 数据湖是没有结构的,所以它使用起来非常灵活。而数仓在使用之前必须建立结构,不能随意改动。
数据湖存储起来非常方便,为了保证敏捷开发,
是无需管理的,对吗?
错!数据湖因为敏捷性,如果没有管理体系,数据湖会变得相当混乱。虽然数据湖存储数据不需要schema,但是必须要进行规范管理,包含清晰地目录结构、数据方便被检索、权限控制、加密存储、提供统一访问的API等等。
Apache Hudi是干什么的?仅仅实现增删改查吗?
Hudi是一个用于构建数据湖的开源工具。在GitHub是很活跃的。我们构建数仓很多时候会选Hive。而构建数据湖我们可以选择Hudi。它提供了数据湖所必要的数据提取、数据管理、血缘追踪等功能,而且可以Hadoop、Spark等大数据框架很好地结合起来。
基于Hudi的数据湖数据是以什么方式存储的?
Parquet方式,可以存储在HDFS中。
Hudi有元数据吗?元数据存储在哪儿?
Hudi是有元数据的,元数据记录了数据操作的时间、数据的提交、分区等等。
Hudi是以什么方式与Spark进行整合的?
以DataSource方式,通过Spark SQL可以较好的操作Hudi。
参考文献:
https://searchaws.techtarget.com/definition/data-lake
https://www.guru99.com/data-lake-architecture.html
https://hudi.apache.org/
http://spark.apache.org/docs/2.4.7/rdd-programming-guide.html