数据湖是一类存储数据自然/原始格式的系统或存储,通常是对象块或者文件。数据湖通常是企业中全量数据的单一存储。 全量数据包括原始系统所产生的原始数据拷贝以及为了各类任务而产生的转换数据,各类任务包括报表、可视化、高级分析和机器学习。
数据湖可以认为是新一代的大数据基础设施。
第一阶段:以Hadoop为代表的离线数据处理基础设施
Hadoop是以HDFS为核心存储,以MapReduce(简称MR)为基本计算模型的批量数据处理基础设施。
第二阶段:Lambda架构
随着数据处理能力和处理需求的不断变化,越来越多的用户发现,批处理模式无论如何提升性能,也无法满足一些实时性要求高的处理场景,流式计算引擎应运而生,例如Storm、Spark Streaming、Flink等。
Lambda架构的核心理念是“流批一体”,如上图所示,整个数据流向自左向右流入平台。进入平台后一分为二,一部分走批处理模式,一部分走流式计算模式。无论哪种计算模式,最终的处理结果都通过服务层对应用提供,确保访问的一致性。
第三阶段:Kappa架构
Lambda架构解决了应用读取数据的一致性问题,但是“流批分离”的处理链路增大了研发的复杂性。因此,有人就提出能不能用一套系统来解决所有问题。目前比较流行的做法就是基于流计算来做。流计算天然的分布式特征,注定了他的扩展性更好。通过加大流计算的并发性,加大流式数据的“时间窗口”,来统一批处理与流式处理两种计算模式。
现在的数据湖都是湖仓一体的,结合了数据湖和数据仓库的优势,将数据仓库中对于数据的严格管理直接实现到了低成本的分布式存储之上
每次写入都生成一个新的元数据文件,记录变更。分区数据在update时,不要删除旧数据,保证新旧共存。元数据中存储具体的文件路径,而不仅仅是分区文件夹
实现:每一次写入操作,创建一个新的json文件,以递增版本号命名,记录本次新增/删除的文件;每当产生N个json,做一次聚合,记录完整的分区文件信息;用checkpoint记录上次做聚合的版本号
数据湖中的ACID
写入流程:先写parquet数据文件,再写json元数据文件
如何确保原子性?
需要从用户可见性入手,用户只会读取以版本号数据命名的json文件,每次都读取到最大的版本号作为数据集的现状。新的写入写完parquet后开始写json文件,使用hash值对json文件命名。直到json文件内容写入完毕,利用hdfs的renameIfAbsent能力将hash值文件名替换为数字文件名,到此为止,commmit完成,新的读取将以数字文件名作为最新版本。
这样读写冲突就已经解决,新的写入除非commit,否则用户读不到;用户正在读的分区,被另一个写入进行了更新,数据不会进行替换,而是共存。
update写入流程
分一下情况讨论:
Add/Drop/Rename
重要:用户并不直接读取parquet文件本身,而是通过数据湖接口读取,如Dataset<Row> ds = simpleDataLake.read(mytable).option(date=2020-01-01)
。数据湖内部会读取应该读的parquet,并在schema上做进一步处理
ID将data和metadata的列名做一一对应,存在以下情况:
我们要根据实际情况来选择,短期来看:每个项目都有一些属于自己的功能:
长期来看:数据湖取代Hive,成为HDFS上的表格式标准是必然的,在选择之前问自己四个问题
数据湖的最新发展状态时湖仓一体,数据湖以低存储成本提供了ACID Transaction、Schema evolution、 Time traverl等高级功能。