Google:使用Cloud Storage统一分析工作负载数据
Google Cloud
当今分析和信息领域的一个关键趋势是Data Lakehouse的概念,这意味着结合不同类型的数据,结构化数据或非结构化数据,以支持多种工作负载和用户类型,可以是BI,可以是AI和数据科学。工作负载可以来自应用程序源,可以来自批量和流式摄取和分析,并统一到一个接口中,例如Apache Iceberg、Hudi或Delta Lake的统一表格式。然后,应用一致的安全和治理模型。目标是为所有分析工作负载和所有用户类型提供一个统一的接口。
这是一个宏伟的愿景,但实际上,尽管顶层有统一的接口,但一旦深入到存储的具体细节,往往会面临数据孤岛的问题。如果存在许多不同种类的工作负载,它们具有不同的性能和语义特征,可能就需要不同类型的存储解决方案,比如本地SSD、持久性硬盘或对象存储。这些工作负载可能需要不同的接口,比如需要类似文件系统的语义。
数据可能分散在不同的地区,甚至不同大陆,这不仅是为了遵守相关法规,也是为了性能考虑,确保存储与计算资源的近距离部署。这一切因素共同作用,形成了数据孤岛,也就是在不同地点存在多个数据副本。当有多个数据副本时,可能会导致数据不一致或无法被用户访问,还可能存在安全模型不一致的问题,因为不同类型的存储可能依赖不同的安全平台。这些问题最终增加了成本和复杂性,削弱了实现分析数据湖的愿景。
我们的目标是在Google Cloud Storage上统一数据。这意味着只需存储一次数据,就可以在任何地方、以任何性能、任何接口、任何规模访问它。
让我们进一步探讨这到底意味着什么。如果你正在构建一个用于分析的统一数据平台,从幻灯片的底部开始看,以Cloud Storage作为统一存储层。客户喜欢Cloud Storage作为对象存储平台,因为它很简单。它提供了一个统一的全局全API端点,它既可靠又经济高效,具有极高的可靠性和可用性,可靠性达到了12个9,可用性为4个9。一些客户已经达到PB级别的存储容量。有了这个统一的存储层,你可以存储各种类型的数据,包括结构化数据如Avro或Parquet,半结构化数据如JSON或XML,以及非结构化数据,比如图像、文本和视频,这些你可能会在AI/ML的应用场景中遇到。所有这些数据的整合服务于分析流程和工具处理。从数据摄取、处理,到管理元数据以获得洞察,再到使用工具进行数据管理的安全控制。它能够支持多种类型的工作负载,无论是直接在Google Cloud上运行,还是利用合作伙伴供应商的分析服务,或者使用像Hadoop、Spark或Kafka这样的开源平台,或是任何组合。最终,这一切都是为了支持最终用户的应用场景,包括BI查询、流式分析、数据科学和ML。这就是如何构建一个统一的数据平台。
我们将从性能开始。如果你正在进行分析查询,你需要快速得到答案。这意味着你需要高吞吐量。由于你可能在不同的区域和位置有计算能力,需要能够在任何地方运行这些工作负载,并确保具有与该计算的本地性能。
从治理的角度来看,你需要确保你在层次结构的所有级别上都有细粒度的访问控制,并且需要确保它与现有的工具集集成。
从可编程性的角度来看,让我们考虑这实际上是应用程序如何与存储接口。你可能需要考虑使用的语义。例如,数据团队习惯于使用本地文件系统,你可能需要弄清楚如何优化这个统一的存储系统以满足应用程序的需求。考虑像Hadoop这样的应用程序,它们期望具有层次结构的行为和性能。
最后,你需要支持所有的工作负载。从生态系统的角度来看,这意味着支持第一方优化的云服务商服务,你可能需要合作伙伴服务进行多云和混合云,然后你可能有自己的管理应用程序,如专有工作负载或开源。
Bradley Kelemen
Google Cloud
[Performance]
Store once, run anywhere
如果你正在运行数据密集型工作负载,性能对你来说绝对是至关重要的。我们理解这一点,并为你提供了一种存储方式,一次存储,到处运行。
为了一次存储和到处运行,你需要解决数据位置难题。我在这里展示了两个客户与数据位置难题作“斗争”的例子。如果你是一家全国零售商,你有多个PB的数据,用户遍布整个大陆,希望访问这些数据。如果你是一家像Snap或Midjourney这样的社交媒体公司,你有多个PB的数据,用户每天运行ML工作负载训练工作负载来处理这些数据,并且他们希望访问GPU和TPU。
如何解决这个位置难题?首先得决定数据的存放位置。你可以选择放入区域桶(Regional bucket)中,区域桶成本低廉,但它的访问权限仅限于一个特定区域。如果需要,也可以放入双区域桶(Dual-Region bucket),这样就能从两个区域进行访问,不过这种选择仍然存在一定的局限性。更灵活的做法是使用多区域桶(Multi-Region bucket),这是Google Cloud Storage所独有的,它提供了更大的灵活性,尽管如此,你还是需要考虑到跨越较长网络路径的问题。
那么,解决方案是什么呢?可以利用多区域桶结合Anywhere Cache功能。这样,就能够实现数据的一次性存储,并在大陆的任何地方进行访问和运行。Anywhere Cache作为一个基于区域的本地SSD(Zone-local SSD)支持的只读缓存,能够有效地提升数据读取的效率。以右侧的图为例,展示了一个设置了多区域桶的配置,在西海岸、中西部和东海岸均部署了缓存节点。当进行首次数据读取时,桶会将数据发送到VM,同时将这些数据缓存到本地。之后的读取操作,将直接从与该VM位于同一区域的缓存中获取数据。
Anywhere Cache的启用非常简单。仅需在桶级别进行设置,便能自动根据需求扩展到相应的规模。无需预先分配可能用不到的大TB级存储空间。此外,Anywhere Cache与现有的API完全兼容,这意味着无需修改现有的代码或将数据迁移到新的桶中,它与现有桶兼容。最重要的是,Anywhere Cache确保了数据的一致性。如果部署了多个缓存,它们将提供统一的数据视图。当底层存储的数据更新后,缓存会检测到这一变化,进行一次未命中,自动从存储桶中重新获取最新数据,并刷新缓存中的内容。
在什么情况下使用Anywhere Cache呢?当追求快速获取数据处理结果并希望高效利用计算资源时,Anywhere Cache就能派上用场。Anywhere Cache能够提供10TB/s吞吐量。举例来说,如果在一个存储桶上启用了四个缓存,该桶可以从所有缓存聚合中每秒获得40TB的数据吞吐量。这一性能远远超出了大多数其他缓存解决方案所能提供的吞吐量。
Anywhere Cache非常适合处理大规模数据集。它在容量上超越了几乎所有其他缓存解决方案。在每个Anywhere Cache中,可以存储高达1PB的数据。Anywhere Cache通过自动调整规模来降低成本,仅需为实际使用的资源付费。例如,如果只缓存了5TB的数据,就无需为10TB的存储空间预付费用。付费会根据缓存的数据量自动调整——无论是5TB、10TB还是减少到2TB。此外,由于Anywhere Cache避免了长距离的网络传输,因此还能减少网络传输成本,从而进一步节约开支。
Anywhere Cache确保提供的数据始终是一致的,因此无需担心在使用它与本地SSD或你的缓存集群配合时,需要不断地手动更新以保持数据的新鲜度。我们保障了缓存中所有数据的一致性。此外,Anywhere Cache的部署非常简单快捷,只需通过存储桶的设置来启用它,之后工作负载便能够无缝运行,无需进行任何额外的修改或调整。
怎么用Anywhere Cache呢?使用Anywhere Cache总共分为四个步骤:首先是发现,然后是创建,再接着是监控,最后是管理。在发现阶段,我们提供了一个推荐工具,它可以帮助用户确定在何处部署缓存以及应该采用什么样的设置。这个工具能够模拟出过去七天内桶缓存的使用情况。完成发现阶段后,就可以进行创建操作了。一旦缓存在桶上被创建出来,接下来就可以对缓存进行监控,以便于收获效益和进行故障排查,最后一步是进行管理。
让我们来实际看看这是怎么运作的。接下来,我将进行一个演示,向大家展示它的工作流程。
-----[演示开始]-----
这里是桶列表。Anywhere Cache适用于多区域、双区域或单区域桶。在设置缓存时,选择包含源数据的桶,缓存位置应与你的VM在同一区域。我已启用了缓存状态列。如果你想配置缓存,可以单击缓存状态。这将进入配置界面。在这里,你可以看到你可以创建缓存的区域。如果你不确定我们的缓存是否会对你有帮助,你可以通过选择带有灯泡图标的区域来查看推荐。
推荐器基于你过去七天的使用情况执行缓存模拟。推荐基于三个指标。第一个指标,缓存命中率,显示了如果启用了缓存,将有多少百分比的字节从缓存中提供。这为你提供了你的工作负载可能会加速的可能性。
第二个指标显示了通过使用Anywhere Cache你可能节省的成本。如果你使用的是多区域桶,你需要支付从该桶读取数据的网络数据传输费用。使用Anywhere Cache允许你避免那些费用。在这个例子中,我们还看到每周约节省了66000美元。缓存还提供了大量的额外吞吐量。
最后一个指标显示,缓存将提供接近900Gbps的峰值吞吐量。推荐器还为你提供了一个估计成本。在这种情况下,我们看到成本将是每周大约1400美元。指标和成本基于TTL设置。推荐器模拟多个TTL并选择成本最低的一个。我这里显示的是一天。
一旦你选择了一个区域,你可以接受推荐的TTL或更改它。你可以选择1小时到7天之间的选项。TTL是自上次访问以来的时间。另一个重要设置是第二次访问时摄取的设置,它在右侧。在许多情况下,这是减少缓存成本的好方法。如果你使用第二次访问设置,你将只略微降低命中率,同时大幅降低缓存成本。
在选择区域后,我这里选择两个。你可以保存配置。一个长时间运行的操作开始创建缓存。创建缓存大约需要40分钟。
与此同时,我将转到一个我已经创建了缓存的桶。
当创建缓存完成后,你可以转到桶页面的可观察性选项卡,并且你可以看到这里启用的缓存总数为两个。如果你查看图,左侧的图显示了随时间变化的缓存命中率,而右侧的图显示了随时间被摄取到缓存中的数据量。向下滚动,我们看到了随时间变化的缓存命中吞吐量和缓存未命中吞吐量。
在观察了你的缓存行为之后,你可能想要采取行动来管理缓存。从这个屏幕,我们将返回到上面。你可以编辑配置。你可能想要暂停一个缓存。暂停缓存会导致停止向缓存中摄取数据,同时允许已经缓存中的数据继续被读取。
这个特性对于故障排除非常有用。例如,如果你有一个“流氓”进程,这是一个方便的方式来隔离问题。它也是将重要热门数据与其它数据隔离开来的一种方式。将重要数据扫描到缓存中,然后暂停缓存以防止不重要的数据被摄取到缓存中。最后,你可以拆除缓存或禁用它。
-----[演示结束]-----
在性能方面,最后提一下的是,我们推出了一个名为gRPC的新API。gRPC是一个出色的工具,它能够显著减少响应时间,并提升计算资源的利用率。与JSON API相比,gRPC能够提供更低的延迟,并缩短程序的整体执行时间。gRPC API支持C++、Java和Go等客户端库。如果你有Hadoop或Spark工作负载,包括使用DataProc的场景,也可以通过Cloud Storage Connector使用gRPC。此外,如果你正在使用Dataflow,gRPC也能够与Cloud Storage的管道服务兼容。
Google Cloud
[Governance]
Help lock down your data with fine-grained access control
让我们来谈谈治理。对于许多人来说,一个重要的主题是如何锁定数据,特别是具有细粒度访问控制。
让我们从一些客户示例开始。例如,像Verizon或AT&T这样的通信服务提供商可能有一个使用DataProc管理Spark分析工作负载的多租户分析平台。他们需要管理存储在Cloud Storage桶中的表和分区的权限,确保每个租户访问特定数据。虽然IAM权限可以帮助一致地锁定数据,但桶级别的粒度可能不足以满足具有许多文件夹或行和列的高度分区的工作流程。
为了应对这一挑战,我们推出了一项名为“管理文件夹”(Managed folders)的新功能,这是Cloud Storage中的一项全新GA特性,它能够提供更为精细的IAM控制。管理文件夹是一种特殊的资源,它允许用户为拥有相同前缀的一批对象集中设置IAM权限。比如说,如果将前缀设置为"A/B/",那么就可以管理所有带有这个前缀的对象。这个功能可以无缝地在现有的存储桶中启用,无需对应用程序代码做任何修改。同时,我们在UI中加入了文件夹浏览器,以便能够以层级结构的方式查看和管理Cloud Storage环境。
[Programmability]
Optimize your storage with file-oriented behavior and semantics
接下来,来谈谈可编程性。如何利用文件导向的行为和语义来优化存储。尽管对象存储本质上是一个扁平化的命名空间,在UI或CLI中所看到的文件夹实际上是通过特定的前缀来模拟的。这种做法可能会给那些需要文件系统行为支持的应用程序带来一些挑战。以Nuro Cruise为例,这是一家提供自动驾驶软件的供应商,他们将Cloud Storage桶用作ML训练和运营的主要数据存储库。数据科学家们通常更习惯于本地文件系统的语义,而不是对象存储的语义,这可能会导致一些效率不高的操作,比如需要下载数据到本地进行处理。
为了解决这个问题,Cloud Storage FUSE提供了一个解决方案,它允许用户在客户端上将Cloud Storage桶挂载为一个本地文件系统。这样,用户就能够直接对存储桶中的数据进行迭代处理,从而减少了计算资源的空闲时间。Cloud Storage FUSE已经GA,它易于部署,并且已经与GKE、Vertex AI和深度学习等产品实现了集成。
在Next大会上,我们宣布了FUSE File Cache的GA,它支持将本地目录作为缓存,以加快数据读取速度,特别是对于小文件和随机I/O操作。这意味着数据加载将更加迅速。根据我们的测试,训练时间缩短了59%,TCO降低了58%。Cloud Storage FUSE是一个极佳的解决方案,它将存储桶作为顶层,以文件系统的语义发布,但存储桶本身还是保持扁平结构,这可能会引发性能问题。
让我们以一个将数据分析平台迁移到Google Cloud的软件服务提供商为例,比如Uber和Activision Blizzard。他们运行的是Hadoop生态系统工具,如Hadoop和Spark,这些工具通常需要HDFS来进行文件优化操作。当使用类似对象存储的扁平命名空间时,可能会遇到一些问题。
例如,一个常见的Hadoop处理任务是执行一个Hadoop作业,该作业获取所有文件,将它们放入一个临时文件夹中,处理这些文件,然后将该文件夹重命名为最终目的地。在传统的文件系统中,重命名操作非常简单:只需将文件夹重命名即可。但在对象存储中,由于所谓的“文件夹”实际上并不存在,实际上是将前缀下的所有对象复制、删除并移动到新的前缀下。这意味着,如果有数百或数千个对象,用户就无法确定重命名操作是否已经完成,对象是否已经移动,文件夹是否已经从源位置移动到目标位置。因此,重命名操作不是原子性的。
另一个问题是,如果你试图在任何时刻列出存储桶中的所有文件夹层次结构。在当前的对象存储中,你需要对每个前缀执行一个list object的操作,获取其下的子前缀,然后在这些子前缀上执行列出对象的操作,直到完全映射出整个文件夹的层次结构。这可能导致效率低下、可靠性和一致性问题。
那么,我们如何优化存储桶,使其开始呈现出更明显的层次结构呢?这就是我们今天非常兴奋地宣布即将推出的Hierarchical Namespace Buckets预览版的原因。Hierarchical Namespace Buckets是一个新的桶创建选项,它优化了存储布局。因此,不再有扁平命名空间,而是有文件夹和位于这些文件夹中的对象,并由API资源支持,这真正针对的是面向文件和数据密集型工作负载。
一个显著的帮助是提升了数据的吞吐量。以Cloud Storage为例,无论是读取还是写入操作,在初始阶段都存在一定的QPS限制。然而,随着工作负载的增加,这个限制会线性增长。在启用了HNS的存储桶中,存储布局的优化可以让你对对象的读取和写入操作的初始桶QPS提高至原来的8倍,这表示你可以更快地启动应用程序,并实现更迅速的扩展。
我们还引入了类似文件系统的增强特性,包括新的文件夹资源和可以管理的API,以及一个可以原子性重命名文件夹及其所有子内容的重命名文件夹API。这真正实现了我们之前讨论的原子文件夹操作场景。此外,我们还提供了一个列出文件夹的API,它允许你在存储桶的任意位置列出文件夹的层次结构。最后,如果你需要进行更精细的访问管理,可以使用我们先前讨论的管理文件夹功能,在层次结构的任何文件夹上附加权限。如果你重命名了该文件夹,相应的权限也会随之迁移。
所有这些新特性都与我们现有的生态系统兼容,因此它支持对象存储API。我们支持Cloud Storage连接器,以及DataProc用于Hadoop和Spark工作负载。如果你想在客户端获得一个更接近文件系统的使用环境,你可以在HNS桶上使用Cloud Storage FUSE。
Google Cloud
[Ecosystem]
One data platform, any workload
我们都知道,每个人在他们自己的工作领域中都有一套熟悉的生态系统,而要改变这个生态系统是相当具有挑战性的。因此,我们提供了一个能够与任何生态系统兼容的平台。您可以自由选择使用的工具,无论您是利用Google的一系列工具,比如BigQuery、DataProc和DataFlow,还是选择使用合作伙伴的产品,如Databricks、Confluent或Palo Alto Networks。甚至,如果您更倾向于使用开源技术,比如Hadoop、Spark或PyTorch来自己构建解决方案,Cloud Storage都能为所有这些工具提供一个统一的数据源,确保数据的一致性和真实性。
Uber
首先,谈一下Uber批处理数据平台的一些背景。
这个平台规模庞大,每天被Uber内部的使用者频繁操作,对公司的日常运营至关重要。我们服务的群体涵盖了公司半数的员工,他们使用这个平台执行各种角色和广泛的工作负载。我们每周支持着800万次的查询和10万条活跃的数据管道。自2023年1月起,我们开始将这个平台迁移到GCP,迄今为止,我们已经上传了超过100PB的数据。在此之前,我们是一家典型的互联网公司,利用Hadoop生态系统作为我们的数据湖。
那么,为什么我们要进行这次迁移呢?第一个原因是简化操作。通过与GCP合作,我们能够大幅简化我们的供应链管理和硬件管理。我们能够解锁新能力。在2009年Uber成立时,Hadoop生态系统对Uber来说是自然而然的选择,并且在过去的10多年里为我们提供了良好的扩展。但现在我们开始遇到扩展限制,这些限制不仅仅是软件相关的。我们也遇到了硬件相关问题。例如,我们拥有的一些专门的HDFS设备越来越难以采购。最后一个原因是提高生产力。Uber工程师越少担心基础设施问题,他们就越能专注于对Uber有更高影响的工程工作。
这是我们在GCP上的一个简化的数据湖视图,我们称之为CloudLake。在顶部,你可以看到我们支持的不同工作负载:仪表板、自动报告、临时分析以及开发和运行ML模型。为了支持这些工作负载,我们有多种数据工具,我们已经将它们归类为BI工具、编排和元数据平台。为了驱动整个平台,我们将事件数据捕获到Kafka中,并将其调整到数据湖的存储层。这里的存储层已经用Google Cloud Storage替换了HDFS,但我们保留了与HDFS一起使用的Parquet和Hudi表和文件格式。在右侧,是安全层,由Kerberos或TokenBroker提供支持。我们有由Spark和Presto提供的批量分析,以及由Flink和Pino支持的实时分析。所有这些都利用了YARN和Kubernetes进行计算。
接下来,我将讨论作为现代化努力的一部分,我们必须克服的一些挑战。第一个是如何保持HDFS的性能一致性。在我们开始之前,普遍的共识是我们无法做到这一点,但GCP向我们保证我们可以,并与我们合作了去年的多个计划,使这成为现实。例如,当我们开始使用gRPC GCS连接器的预GA版本进行一些初步测试时,我们看到的性能比JSON客户端要低得多。但现在,在与Google工程师合作后,我们在它们之间实现了性能一致性,这为我们带来了巨大的性能提升。我们与GCP合作启用了并行复合上传,这也给我们带来了显著的提升,写入吞吐量提高了高达40%。我们共同进行了Spark优化,增加了可观察性,以实现对我们的Spark工作负载进行更精细的调整,我们还没有完成。还有更多的事情要做。我们很高兴听到刚刚提到的HNS桶。我们已经开始对它进行一些初步的Beta测试,并且我们对它将带来的性能提升和一致性增强感到兴奋。
下一个大问题是,如何在不影响到平台用户的情况下进行这次迁移,这些用户是Uber的其它内部员工。如前所述,他们每天使用这个平台进行日常运营。我们在这里做了很多工作,以确保Google Cloud Storage对数据平台的用户看起来和HDFS一样。我们做的第一件事是,将Uber内所有HDFS客户端标准化并强制使用一个官方版本,这使我们能够提供一个API来连接HDFS和GCS。
我们创建了一个名为Data Mesh的新服务,它进行了很多重的工作,隐藏了HDFS和GCS之间的差异。例如,它管理HDFS文件和文件夹与对象和桶之间的差异映射。这就是我们确保在存储层次结构的正确级别应用访问控制的方式,以便我们不会达到硬性限制,并且它也是我们实施OR级别治理等策略的方式。
我们还与GCP建立了深入的合作伙伴关系,创建了一个全新的安全层,我们称之为存储访问服务,这弥合了Hadoop安全模型和GCP的IAM模型之间的差距。这基于GCP的TokenBroker代码库,它允许我们使用Kerberos来管理GCS资源。
最后一个大挑战是,我们如何在保持本地和云端同时进行这次多年的迁移。因此,首先,我们必须进行详细的规划,以确保存储和计算工作负载的最佳配对,以便我们有本地读写。我们创建了一项新服务,它不仅自动复制和验证本地和云之间的数据,还根据所需数据的位置代理工作负载,以便随着我们越来越多地采用云服务,工作负载的运行位置和数据的存储位置对平台用户来说是透明的。
最后一个是容量规划。我们已经与GCP进行了详细的容量规划,以便我们知道每周核心级别上云的容量何时可用,这使我们有信心知道,随着我们在本地停用容量,相应的云容量是可用的。这避免了我们支付双重“泡沫税”,并拥抱了我们内部称为拥抱任务曲线(Hug the curve)的哲学。
总结来说,通过与GCP合作,我们正在现代化我们的开源数据湖。我们这样做的同时,保持了性能预期,避免了对我们用户的痛苦迁移,并利用了现有的本地容量,直到寿命结束。
--【本文完】---
近期受欢迎的文章:
更多交流,可添加本人微信
(请附姓名/关注领域)