数据湖学习文档

数据湖学习文档

参考资料:https://segment.com/blog/cultivating-your-data-lake/

培育数据湖
我们经常听到企业希望对客户数据做更多的事情。他们想要获得数据信息,他们想要提供更好的客户体验,最重要的是,他们只想了解他们的客户。

到达那里并不容易。您不仅需要收集和存储数据,还需要识别有用的部分并根据洞察采取行动。

在Segment,我们已经帮助成千上万的企业走上了数据获取的道路。我们多次看到的一个成功的技术是建立一个工作数据湖。

数据湖是一个集中的存储库,它存储结构化和非结构化数据,允许您在一个灵活的、经济有效的存储层中存储大量数据。数据湖越来越受欢迎,一方面是因为企业拥有的数据比以往任何时候都多,另一方面也是因为收集和存储数据从来没有像现在这样便宜和容易。

在这篇文章中,我们将深入研究在使用数据湖时要考虑的不同层。

我们将从一个对象存储开始,比如S3或谷歌云存储,作为一个廉价而可靠的存储层。
接下来是查询层,如Athena或BigQuery,它允许您通过一个简单的SQL接口来探索数据湖中的数据。
中心部分是一个元数据存储,如AWS Glue目录,它将所有元数据(其格式、位置等)与您的工具连接起来。
最后,您可以利用顶层的转换层(如EMR)来运行聚合、写入新表或以其他方式转换数据。

作为AWS中所有这些工具的忠实用户,我们将分享一些关于AWS生态系统中客户数据的示例、提示和建议。这些相同的概念也适用于其他云和更远的地方。

S3存储层:

如果您从这篇博客文章中获得了一个想法,那就是:在S3中存储数据的原始副本。

它便宜、可扩展、非常可靠,并且与AWS生态系统中的其他工具配合得很好。S3的全部存储费用很可能每月不到100美元。如果我们纵观我们的整个客户基础,只有不到1%的客户每月为分段收集的数据支付超过100美元的S3账单。

也就是说,S3的简单性是一把双刃剑。虽然S3是保存所有数据的好地方,但它常常需要做大量的工作来收集数据、加载数据并实际获得所需的信息。

在S3上收集和存储数据时,有三个重要的因素需要牢记:

编码——数据文件可以用任意多种方式编码(CSV、JSON、Parquet、ORC),每种方式都有很大的性能影响。
批处理大小——文件大小对上传策略(和数据新鲜度)和查询时间都有重要影响。
分区方案——分区是指数据的“层次结构”,数据的分区或结构化方式会影响搜索性能。

							在数据湖中构建数据

我们将更深入地讨论其中的每一个,但是首先值得了解的是数据是如何首先进入数据湖的。

有许多方法可以将数据放入S3,例如通过S3 UI或CLI上传数据。但是如果您讨论的是客户数据,那么很容易通过段平台将数据交付给S3。Segment平台提供了收集、清理和控制第一方客户数据的基础设施,并将所需数据准确地发送到所需的所有工具中。

编码

文件的编码对查询和数据分析的性能有重大影响。对于较大的工作负载,您可能希望使用诸如Parquet或ORC之类的二进制格式(我们已经开始在本地支持这些格式了)。如果你想要测试访问,请联系!)。

要理解其中的原因,请考虑一下机器在读取JSON与Parquet时必须执行的操作。

查看JSON时,数据看起来是这样的:
{ ‘userId’: ‘user-1’, ‘name’: ‘Lauren’, ‘company’: ‘Segment’ }
{ ‘userId’: ‘user-2’, ‘name’: ‘Parsa’, ‘company’: 'Segment }
{ ‘userId’: ‘user-3’, ‘company’: ‘Microsoft’, ‘name’: ‘Satya’ }
{ ‘userId’: ‘user-4’, ‘name’: ‘Elon’, ‘company’: ‘Tesla’ }
在这里,我们不仅要解析整个消息,还要分别解析每个键和每个值。因为每个JSON对象可能有不同的模式(而且是完全无序的),所以我们必须对每一行做大致相同的工作。

此外,即使我们只是挑选公司或名称,我们也必须解析所有数据。没有“捷径”可以让我们跳到给定行的中间。

与拼花地板相比,我们看到了一个非常不同的模式。在Parquet中,我们预先定义了模式,并最终将数据列存储在一起。下面是之前以拼花格式转换的JSON文档示例。您可以看到用户一起存储在右侧,因为它们都在同一列中。

右侧显示存储在一起的用户
读取器不必解析并在内存中保留对象的复杂表示形式,也不必读取整个行来挑选一个字段。相反,它可以快速跳转到它需要的文件部分并解析出相关的列。

下面是一些查询JSON和Parquet的具体基准测试,而不只是相信我的话。

在这四个场景中,我们都可以看到使用拼花地板的巨大好处。

在这里插入图片描述
如您所见,我们需要在每个实例中查询的数据对于拼花来说是有限的。对于JSON,我们需要每次都查询每个JSON事件的完整体。

批量大小

批处理大小(即每个文件中的数据量)很难调优。批量太大意味着在出现打嗝或机器故障时,您必须重新上传或重新处理大量数据。拥有一堆太小的文件意味着您的查询时间可能会更长。

批量大小也与编码相关,我们在上面已经讨论过了。某些格式如Parquet和ORC是“可分割的”,文件可以在运行时被分割和重新组合。在某些条件下,JSON和CSV是可分割的,但通常不能分割以获得更快的处理速度。

通常,我们尝试和目标文件的大小从256 MB到1 GB不等。我们发现这是最佳的整体性能组合。

分区

当每个批处理中开始有超过1GB的数据时,一定要考虑如何分割或分区数据集。每个分区只包含数据的一个子集。这通过减少使用诸如雅典娜之类的工具查询或使用EMR处理数据时必须扫描的数据量来提高性能。例如,按日期划分数据是一种常见的方法。

查询

最后,值得理解的是,仅仅将数据放在S3中并不能真正直接帮助您完成本文开头所讨论的任何事情。这就像有一个硬盘,但是没有CPU。

有许多方法可以检查这些数据—您可以下载全部数据,编写一些代码,或者尝试将其加载到其他数据库中。

但最简单的是编写SQL。这就是雅典娜发挥作用的地方。

查询层:雅典娜🔎

一旦您将数据放入S3,开始研究您所收集的数据的最佳方法就是通过Athena。

Athena是一个由AWS管理的查询引擎,它允许您使用SQL查询S3中的任何数据,并且可以处理大多数结构化数据的常见文件格式,如Parquet、JSON、CSV等。

为了开始雅典娜,您只需要提供数据的位置、格式和您关心的特定部分。特别是片段事件具有特定的格式,我们可以在创建表时使用这种格式,以便进行更简单的分析。

设置

下面是一个在Athena中设置表模式的例子,我们将使用它来查看我们按类型接收了多少消息:

CREATE EXTERNAL TABLE IF NOT EXISTS segment_logs.eventlogs (
anonymousid string , # pick columns you care about!
context map<string,string> , # using a map for nested JSON
messageid string ,
timestamp Timestamp ,
type string ,
userid string ,
traits map<string,string> ,
event string
)
PARTITIONED BY (sourceid string) # partition by the axes you expect to query often, sourceid here is associated with each source of data
ROW FORMAT SERDE ‘org.apache.hive.hcatalog.data.JsonSerDe’
LOCATION ‘s3://your-s3-bucket/segment-logs’ # location of your data in S3

除了创建表,您还需要添加特定的分区:

ALTER TABLE eventlogs ADD
PARTITION (sourceid=‘source1’) LOCATION ‘s3://your-s3-bucket/segment-logs/sourceid=source1/’ # sourceid here is associated with each source of data
PARTITION (sourceid=‘source2’) LOCATION ‘s3://your-s3-bucket/segment-logs/sourceid=source2/’
PARTITION (sourceid=‘source3’) LOCATION ‘s3://your-s3-bucket/segment-logs/sourceid=source3/’
PARTITION (sourceid=‘source4’) LOCATION ‘s3://your-s3-bucket/segment-logs/sourceid=source4/’

有许多方法可以对数据进行分区。在这里,我们根据每个客户的源代码进行了分区。当我们查看特定的客户时,这对我们很有用,但是如果您查看所有的客户,您可能希望按日期进行分区。

查询时间!

让我们从上表中回答一个简单的问题。假设我们想要知道在过去的一天中,我们看到的给定数据源的每种类型的消息有多少条——我们可以简单地运行一些SQL,从我们刚刚在Athena中创建的表中找出:

select type, count(messageid)
from eventlogs
where sourceid=‘source1’
and date_trunc(‘day’, timestamp) = current_date
group by 1
order by 2 desc

对于所有查询,Athena的成本与如何划分数据及其格式密切相关。它还取决于扫描多少数据(每TB 5美元)。

在扫描JSON时,由于它的结构,您将每次扫描整个记录(参见上面的示例)。或者,您可以为只包含您关心的列的数据子集设置Parquet,这对于限制表扫描和因此限制成本非常有用。这也是为什么Parquet可以更快—它可以直接访问特定的列,而无需扫描整个JSON。

元数据:AWS胶水🗺

保持当前的

Athena的一个挑战是在向S3添加新数据时保持表的更新。雅典娜不知道您的新数据存储在何处,因此您需要更新或创建新的表(类似于上面的查询),以便为雅典娜指出正确的方向。幸运的是,有一些工具可以帮助管理模式并使表保持最新。

AWS Glue目录是一个中心位置,在其中存储和填充AWS中所有工具的表元数据,包括Athena。您可以使用开箱即用的爬行器来扫描数据,也可以通过Glue API或Hive来直接填充目录。在下面的图表中,您可以看到这些是如何组合在一起的。

使用元数据填充后,Athena和EMR在查询或访问S3中的数据时可以引用位置、类型等的Glue目录。

From: https://docs.aws.amazon.com/athena/latest/ug/glue-athena.html
计算层:EMR

除了一次性查询和探索性分析之外,如果您想修改或转换数据,像EMR (Elastic Map Reduce)这样的工具不仅可以读取数据,还可以将其转换为新的表。如果您想要将数据的格式从JSON转换为Parquet,或者您想要聚合%的用户在过去一个月完成注册流并将其写入另一个表以供将来使用,那么您可能需要编写。

操作EMR

EMR在EC2 (AWS的标准计算实例)之上提供托管的Hadoop。一些代码和配置是必要的-我们在内部使用Spark和Hive大量在EMR之上。Hive为您的数据提供了一个SQL接口,Spark是一个数据处理框架,它支持许多不同的语言,如Python、Scala和Java。下面我们将通过一个示例对每个示例进行更深入的解释。

在模式方面,使用EMR管理数据类似于雅典娜的操作方式。您需要告诉它数据的位置及其格式。您可以在每次需要运行作业或利用中心转移(如前面提到的AWS Glue目录)时这样做。

在前面的示例的基础上,让我们使用EMR来查找不仅在过去的一天中,而且在过去一年中的每一天中,每种类型的消息的数量。这需要通过比我们在雅典娜做了更多的数据,这意味着我们应该做一些优化,以帮助加快这一点。

数据预处理

我们应该进行的第一个优化是将数据从JSON转换为Parquet。这将允许我们大幅度减少扫描最终查询所需的数据量,如前面所示!

对于这个JSON到Parquet文件格式转换,我们将使用Hive,然后转向Spark进行聚合步骤。

Hive是一个数据仓库系统,它有一个用于处理大量数据的SQL接口,从2010年开始出现。当您需要一次对大量数据执行大量读写操作时,Hive确实很出色,这正是我们将所有历史数据从JSON转换成Parquet时所需要的。

下面是一个如何执行JSON到Parquet转换的示例。

首先,我们用我们想要的最终拼花格式创建目标表,这可以通过Hive来完成。

CREATE EXTERNAL TABLE test_parquet(
anonymousid string ,
context map<string,string> ,
messageid string ,
timestamp Timestamp ,
type string ,
userid string ,
traits map<string,string> ,
event string
)
PARTITIONED BY (dt string) – dt will be the prefix on your output files, i.e. s3://your-data-lake/parquet/dt=1432432423/object1.gz
STORED AS PARQUET – specify the format you want here
location ‘s3://your-data-lake/parquet/’;

然后我们只需从原始的JSON表中读取数据,并插入到新创建的拼花表中:
INSERT INTO test_parquet partition (dt)
SELECT anonymousid, context, messageId, timestamp, type, userid, traits, event
FROM test_json;

为了实际运行这个步骤,我们需要创建一个EMR作业,在它后面放置一些计算。你可以做到这一点,通过提交作业EMR通过用户界面:
或者,通过CLI提交工作:

EMR CLI example job, with lots of config!

aws emr add-steps
–cluster-id j-xxxxx
–steps Type=spark, Name=SparkWordCountApp, \
Args=[
–deploy-mode,cluster,–master,yarn,–conf,spark.yarn.submit.waitAppCompletion=false,–num-executors,5,–executor-cores,5,–executor-memory,20g,s3://codelocation/wordcount.py,s3://inputbucket/input.txt,s3://outputbucket/], \
ActionOnFailure=CONTINUE

聚合

现在我们已经有了拼花格式的数据,我们可以利用Spark来计算每种类型接收到的消息的总数,并将结果写入最终表,供以后参考。

Spark对于在数据上运行计算或聚合非常有用。它支持SQL以外的语言,如Python、R、Scala、Java等,这些语言有更复杂的逻辑和库。它还具有内存缓存,所以中间数据不会写入磁盘。

下面是一个根据类型进行messageid聚合的Spark作业的Python示例。
from datetime import datetime, timezone, timedelta
from pyspark.sql.functions import col, when, count, desc

S3 buckets for reading Segment logs and writing aggregation output

read_bucket_prefix = ‘s3://bizops-data-lake/segment-logs/source1’
write_bucket_prefix = “s3://bizops-data-lake-development/tmp/segment-logs-source1”

get datestamp for prior year

today = datetime.now()
last_year_partition = datetime.strftime(today - timedelta(years=today.weekday(), years=1), ‘%Y-%m-%d’)
last_year_ds = datetime.strptime(last_year_partition, ‘%Y-%m-%d’)

“”"
obtain all logs partitions of the year
sample filenames:
[
‘s3://bizops-data-lake/segment-logs/source1/1558915200000/’,
‘s3://bizops-data-lake/segment-logs/source1/1559001600000/’,
‘s3://bizops-data-lake/segment-logs/source1/1559088000000/’,

]
“”"
read_partitions = []
for day in range(365):
next_ds = last_year_ds + timedelta(days=day)
ts_partition = int(1000*next_ds.replace(tzinfo=timezone.utc).timestamp())
read_year_partitions.append("{}/{}/".format(read_bucket_prefix, ts_partition))

bucket partition for aggregation output

sample ‘s3://bizops-data-lake-development/tmp/segment-logs-source1/week_ds=2019-05-27/’

write_year_ds = “{}/week_start_ds={}/”.format(write_bucket_prefix, last_year_partition)

read logs of last year, from pre-processing step. Faster with parquet!

df = spark.read.parquet(read_year_partitions)

aggregate by message type

agg_df = df.select(“type”, “messageid”).groupBy(“type”).agg(
count(messageid).alias(“message_count”),
)

writing Spark output dataframe to final S3 bucket in parquet format

agg_df.write.parquet(path=write_year_ds, compression=‘snappy’, mode=‘overwrite’)

这是最后一步,agg_df.write。它获取以中间格式(DataFrame)存储的更新后的聚合,并将这些聚合以拼花格式写入新桶中。

结论

总之,有一个强大的工具生态系统,可以从数据湖中积累的大量数据中获取价值。

一切都从将数据放入S3开始。这为您提供了一个非常便宜、可靠的存储所有数据的地方。

从S3中,很容易使用Athena查询数据。Athena非常适合进行探索性分析,它有一个简单的UI,允许您针对S3中的任何数据编写SQL查询。拼花可以帮助减少你需要查询的数据量,节省成本!

AWS Glue使S3数据查询更加容易,因为它是数据所在位置的中心转移。它已经与Athena和EMR集成,并具有方便的爬行器,可以帮助映射数据类型和位置。

最后,EMR帮助您将数据湖提升到下一个级别,通过Spark、Hive等灵活性来转换、聚合和创建数据的新滚动。它的管理可能更复杂,但是它的数据操作能力是首屈一指的。

在分部,我们帮助实现与这些相同系统的无缝集成。我们的S3目的地允许客户在自己的AWS帐户中拥有所有客户和事件数据的新副本。

我们正在扩展文件格式选项,并与AWS Glue metastore集成,让这一切变得更加容易。这样,你就总能拥有一个最新的模式来更新你的最新数据。如果你想成为测试的一部分,请给我们写信!

特别感谢Parsa Shabani, Calvin French-Owen和Udit Mehta

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据湖解决方案和相关资料集合,供大家学习参考。包括: 2020阿里云数据湖高峰论坛发布资料合集: 阿里云数据湖应用实践白皮书; 阿里云云原生数据湖体系; 数据湖解决方案-本地生活行业应用最佳实践; 数据湖解决方案-互金行业应用最佳实践; 数据湖解决方案-互娱行业应用最佳实践; 数据湖解决方案-教育行业应用最佳实践; 数据湖解决方案-游戏行业应用最佳实践; 数据湖解决方案-最佳实践案例集; 数据湖解决方案-AI行业应用最佳实践; 华为数据湖探索用户指南; 华为数据湖治理中心数据治理方法论; 华为数据湖治理中心用户指南; 毕马威数据湖数据管控平台; 城市数据湖-新一代数字经济基础设施; 打造数据增量计算新架构 - 网易数据湖调研&实践; 基于 AWS 数据湖打造 “千人千面”的互联网广告平台; 基于数据湖的精准广告投放系统技术解密; 基于数据湖构建云上的数据分析架构; 基于Serverless的USQL数据湖分析实践; 借助 AWS Lake Formation 构建云上数据湖; 亚马逊云科技:数据湖解决方案; 用大数据来优化数据管理与数据湖建设; 云端的数据湖:现代化的数据架构; AWS数据湖及大数据服务助力 快消行业进行数字化转型; SuperSQL:数据湖时代的高性能SQL引擎; USQL:数据湖分析; 易经布道数据湖

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值