其他
数据湖系列之一 | 你一定爱读的极简数据平台史,从数据仓库、数据湖到湖仓一体
"Data is the new oil." — Clive Humby, 2006
"Data is just like crude. It's valuable, but if unrefined it cannot really be used. It has to be changed into gas, plastic, chemicals, etc to create a valuable entity that drives profitable activity; so must data be broken down, analysed for it to have value." — Michael Palmer
“时间跨度长”的意思是数据存储应尽可能地保存全历史数据。历史数据对企业的重要性,在于 “以史明鉴”,从一个更长的时间维度去观察数据的趋势、健康度等信息。 “来源分散”是因为数据的源头通常是各类业务系统,可能是 MySQL、Oracle 这样的关系型数据库中的数据,也可能业务系统记录的日志。企业还可能购买或采集第三方的数据集作为内部数据的补充。数据平台需要有能力导入不同源头的数据,至于导入后以什么样的格式存储,不同的技术方案有各自的要求。 “集中存储”是为了建立 single source of truth,无论数据的源头在哪里,纳入数据平台之后,数据平台就是唯一的可信来源。这里更多的是指逻辑上的集中存储,在物理上还存在分散的可能性,例如一个企业采用了多云架构,将数据分散存储在不同的云厂商,数据平台对数据使用方屏蔽了数据的实际位置。集中存储同时还意味着更精细的管控,防止数据使用权限扩大到不必要的范围。
一部分计算引擎支持的接口比较开放和底层,对数据格式的要求很宽松。例如 Hadoop MapReduce、Spark 可以直接读取 HDFS 中的文件,这些数据是什么样的格式,引擎本身并不关心,业务自己决定如何解释和适用数据。当然,有一些格式(如 Apache Parquet 等)应用比较广泛,在底层接口之上,引擎可以选择封装出对特定格式的处理逻辑,减少业务的重复开发成本。 另外一部分计算引擎较为封闭,只能支持有限的数据格式,甚至不暴露内部的数据格式,所有的外部数据处理前都必须经过导入的步骤。例如,Apache Doris 的数据如何存储是系统自己决定,好处是可以让存储和计算配合更紧密,性能更好。
一方面,OLTP 数据库的数据存储方式是面向行的 (row-oriented),一个行的数据存储在一起,读取的时候哪怕只需要几个字段,都需要把整行数据都读取出来再提取需要的字段。数据仓库表的字段通常比较多,这就导致了读取效率不高。面向列的 (column-oriented) 的数据存储方式,将不同的列或列族分开存储,在读取的时候就可以只读取需要的部分,这种方式能够有效减少读取的数据量,对数据仓库的场景更为友好。 另一方面,传统 OLTP 数据库依赖单机硬件配置的 scale-up 来提升处理能力,上限较低。而数据仓库场景一次查询读取的数据量非常大,在相同字段上反复调用同样的读取逻辑,很适合做单机、多机的并行处理优化,利用集群的 scale-out 处理能力来缩短查询的时间。这就是 MPP (Massively Parallel Processor) 计算引擎的核心思想。
计算和存储无法分开扩容,而现实中大部分用户对这两种资源的需求不是匹配的,存算一体架构必然会导致其中一种资源的浪费。 存储容量和文件数量爆炸式增长之后,HDFS 的 NameNode 单点架构遇到了元数据性能的瓶颈,企业通过升级 NameNode 节点配置、多套 HDFS 集群或 HDFS Federation 来缓解该问题,但未能根本解决此问题,给数据平台运维人员带来极大的负担。 存储成本也是存算一体架构的一个痛点。HDFS 的 3 副本机制并不适合存储较冷的数据,比纠删码机制的成本要高出至少一倍。在云上还面临副本放大的问题,云厂商提供的云磁盘本身就有副本机制,使用云磁盘搭建 HDFS 的实际副本数更高,可能高达 9 副本。
规模。一个客户数 PB 几十 PB,很多客户共享资源池,累加起来让对象存储的容量轻松达到 EB 级,相应的元数据规模达到万亿级。单个集群服务好 EB 级的容量、万亿级的元数据,需要非常优秀硬核的架构设计,系统的每个部分都不存在扩展性的短板。 稳定性。支持 EB 级的容量、万亿级的元数据,每个集群的机器数量达到数万甚至数十万台,庞大的机器基数下,硬件故障、软件故障是家常便饭。降低甚至消除这些不可控因素的影响,提供稳定的延时和吞吐水平、较低的长尾,拼的是高质量的工程实现和运维能力。 兼容性。尽管对象存储作为数据湖存储已经成为一个共识,但大数据体系内的软件,无论是因为历史包袱的原因,还是因为确实无法改造,在一些场景下依然会依赖 HDFS 特有的一些能力。例如,Spark 依赖 rename 提交任务,利用了 HDFS rename 操作较快的执行速度和原子性保证,但在对象存储的鼻祖 AWS S3 里,rename 不被支持,只能粗糙的通过“拷贝 + 删除”模拟,执行速度很慢且没有原子性保证。如果各家云厂商对象存储的普遍水平是在 70% 的场景下取代 HDFS,那剩下的 30% 的部分就看厂商如何进一步去解决兼容性差的部分,从而让存算分离架构执行得更彻底。
数据仓库好比 iOS,是一个相对封闭的体系,数据流入流出、使用场景约束较多,但胜在简单易用,封闭的体系控制力更强,较容易做存储格式、计算并行等性能上的优化,在一些要求极致性能的查询场景仍占据着主导地位。 数据湖好比 Android,强调开放性,几乎把选择的权利都下放给用户了,可以选择的手机厂商 (计算引擎) 也很多,但用好它需要用户一定的专业能力,用不好会有副作用,很容易导致 “数据沼泽 (Data Swamp)”。
在解决数据沼泽的过程之中,为了让一个很宽松的生态变得更好用,业界的实践实际上就是对数据湖的使用做了很多的约束。有意思的是,这些约束和原来数据仓库做的很多事情是很类似的,例如ETL、ACID、权限控制等。这使得数据湖呈现出数据仓库的一些特征。 业界在尝试了一圈非 SQL 的各种编程接口和交互方式之后,发现很多的场景下,SQL 依然是最佳的选择。数据仓库这些年也越来越开放,对数据湖常用的一些数据格式、表格格式的支持越来越好,除了内置 ETL 的支持,也可以直接把它们当做外部源来处理。这些趋势表明,数据仓库作为一种重要的计算引擎,可以生长在数据湖之上。 数据仓库同样面临存算一体的局限性,也在向存算分离架构迭代。一些系统采用了冷热分离的设计,热数据保存本地节点高速介质上,冷数据下沉到数据湖中,在性能和成本之间取得平衡。另外一些更彻底的云原生数仓系统,全量数据都在数据湖中,通过本地节点的缓存来弥补数据湖速度的问题,这种设计可以简化数据仓库的架构,让数据仓库不需要再关注数据可靠性问题,同时可以让多个只读集群共享同一份数据。 数据仓库领域发展的一些重要技术和方法,也可以被数据湖之上的大数据计算引擎借鉴,反之亦然。例如在 ClickHouse 等数据仓库中成熟应用的计算引擎加速技术,如向量化计算 (vectorization)、LLVM JIT,被借鉴来实现 Spark 的 Native 引擎,和原有的 JVM 引擎相比,Native 引擎的硬件资源利用率更高,计算速度更快。
冷热分离设计。高速文件存储系统将数据湖作为冷数据层。 基于数据湖设计云原生的文件系统。这类文件系统虽然提供文件系统接口,但实际上是一个缓存加速系统,采用的是“缓存层 + 数据湖”的架构。缓存层在计算节点或靠近计算节点的硬件上按需维护热数据的缓存。数据湖存储全量数据,保证数据的可靠性。一旦缓存系统中数据淘汰或丢失,仍然可以从数据湖重新加载数据。
针对数据沼泽问题,元数据层建立必要的数据质量、元数据管理、版本管理、数据流通机制,让企业内部各业务能便捷地使用高质量的数据。 针对一些对元数据、延时有更高要求的业务,如数据仓库、AI、HPC 等,加速层作为对象存储的补充,一般采用高速文件系统或者缓存系统,部署上离计算节点较近,元数据和数据可在加速层和数据湖之间自动流转。为了简化使用,加速层还会搭配上层的作业调度系统,来让数据流转工作更加智能和简单。例如,通过作业调度系统提前预热数据,在数据预热到缓存之后,作业调度系统才开始分配计算资源执行计算,由此可以享受到比数据湖更快的访问速度。
一个手段是,对于特定的计算引擎,使用云厂商的托管或 serverless 的服务代替自建,云厂商的服务内置弹性收缩能力,按需付费,可以让相关的资源利用率控制在合适的范围内,规避了资源共享的问题。 另外一个手段是,用户自己运维的计算引擎使用统一的调度和资源管理平台来分配资源,这方面 Kubenetes 是最流行的选择,如果某种计算引擎还未支持在其上部署,只是时间问题。云厂商通常也会提供优化的Kubenetes 的版本或服务供用户选择。
数据是开放的。计算引擎越来越开放,普遍支持一些标准的数据格式,数据流通越来越容易,业务按需选择最合适的引擎处理计算任务。 技术是开放的。湖仓一体技术架构中的绝大部分重要技术,都以开源项目的形式存在着,没有任何一家企业可以垄断知识产权。厂商发行版和开源版本之间可以相互替代,选择权在用户。技术的开放也促进了跨领域的技术融合,不同的领域之间互相借鉴方法和技术,扬长补短,起到 1 + 1 > 2 的效果。 基础设施是开放的。在湖仓一体解决方案中,云厂商扮演着重要的角色,提供了对象存储、托管大数据服务等基础设施。这些基础设施兼容行业标准,也存在开源替代,客户很容易搭建混合云、多云架构,更好地利用云的弹性。