集中存储层负责管理摄取自各生产程序处的数据,并将其进一步提供给下游应用程序。集中存储层是数据湖的核心,应该能够支持对一切数据类型的存储,具体包括非结构化数据、半结构化数据与结构化数据。随着时间推移,您的数据量可能不断增长,因此集中存储层还应以安全且经济高效的方式实现灵活扩展。
在数据处理管道中,大多数情况我们也会将管道中不同阶段的数据存储进行一份保存,这既可以避免不必要的重复操作,也可以让中间数据同时供多个下游消费程序使用。根据实际场景的需求,这些中间数据可能需要经常更新、临时存储或者长期存储。
Amazon Simple Storage Service (Amazon S3) 具备近乎无限的可扩展性,99.999999999%(11个9)持久性以及原生加密与访问控制功能,因此非常适合作为集中存储方案的底层基础。随着数据存储需求的增长,您可以将数据迁移至低成本层,例如S3 Infrequent Access或者Amazon S3 Glacier,通过多种生命周期管理策略节约存储成本,同时保证原始数据的安全性与完整性。另外,您也可以使用S3 Intelligent-Tiering,借此在数据访问模式发生改变时自动优化存储成本,且不会对性能或运营开销造成任何影响。

区域:亚马逊云计算资源托管在世界各地多个位置。这些位置由 AWS 区域和可用区组成。每个 AWS 区域都是一个单独的地理区域。每个 AWS 区域都有多个"可用区"
存储桶:Amazon S3 将数据有组织到存放到存储桶中,该存储桶是在区域中创建的,并且可以将安全控制策略应用于存储桶,例如指定哪些用户、角色可以进行哪些行为。默认情况下,您可以在每个 AWS 账户中创建多达 100 个存储桶。如果您需要更多存储桶,则可以通过提交服务限额提升请求将账户的存储桶限制提高至最多 1,000 个存储桶。无论您使用许多存储桶还是少量存储桶,性能都没有差异。
对象:Amazon S3 存储最小单元被定义为对象,对于大多数客户来说这些对象是都文件,但可以是任何类型、任何格式的数据文件。对象一般跟在前缀后面,该前缀加对象提供了桶内唯一的 URL。对象具有名称以及与其关联的元数据和标签。
前缀:在桶名字和对象之间的信息,使用'/' (斜线) 分隔路径进行隔断,其中对象存储在存储桶中。存储桶名称、前缀和对象名称的组合以全局方式唯一标识对象。前缀分区是一种Amazon S3机制,用于在一组通用的对象键名之间分配性能。在没有任何共享前缀的情况下,所有对象都根据存储桶名称共享一个分区。

存储桶策略:S3 可以以 JSON 文档的形式存储安全策略,允许您控制哪些用户和角色可以访问存储桶以及如何访问存储桶,以及设置数据在存储桶中存储方式的要求(例如需要加密)。
Amazon S3让多租户环境的构建变得非常轻松,不同用户可以在其中将自己的独特数据分析工具与一组通用数据对接起来。与需要建立多套分布式数据副本的传统解决方案相比,多租户环境能够显著改善成本与数据治理能力。为了进一步降低访问门槛,Amazon S3还提供简单的RESTful API,目前Apache Hadoop以及大多数第三方独立软件供应商(ISV)及分析工具供应商已经在支持这些RESTful API。
在Amazon S3的支持下,您的数据湖能够将存储同计算/数据处理机制拆分开来。在传统Hadoop及数据仓库解决方案当中,存储与计算总是紧密结合在一起,因此对成本与数据处理工作流程的优化总是困难无比。Amazon S3允许您以原生格式存储一切数据类型,并指定任意数量的虚拟服务器执行数据处理。此外,您还可以与多种无服务器解决方案进行集成,例如AWS Lambda、Amazon Athena、Amazon Redshift Spectrum、Amazon Rekognition以及AWS Glue等等——无需置备或管理任何服务器,即可轻松获得数据处理能力。
Amazon Elastic Block Store(简称EBS)提供永久性的块存储卷,可用于AWS云中的Amazon EC2实例。每一个Amazon EBS存储卷都会自动在其所在可用区内复制,保证您的系统免受组件故障的影响,借此实现高可用性与持久性。对于分析类工作负载,您可以将EBS与运行在EC2实例上的各类大数据分析引擎(例如Hadoop/HDFS生态系统或者Amazon EMR集群)、关系数据库与NoSQL数据库(例如微软SQL Server与MySQL,或Cassandra与MongoDB)、流数据与日志处理应用程序(例如Kafka与Splunk)以及数据仓库应用程序(例如Vertica与Teradata)配合使用。
Amazon S3 为您提供了一种简单而强大的机制,用于通过存储桶和前缀在区域中组织数据。在设计数据湖时,您需要仔细设计如何在 S3 中布局数据,并考虑多个区域数据需要如何交互。通常,无论区域如何,全局数据湖都可以以相同的方式布局数据。
根据您的要求,完全有可能只使用单个 S3 存储桶构建企业级数据湖。当然更多情况,您可能需要多个存储桶来实现数据湖的安全性和治理策略
通常,只有在需要深入细分安全策略时,才应为数据湖创建新的存储桶。S3存储桶策略 为您提供一种表达方式来管理大量不同前缀的安全。对于单个存储桶,如果您有非常复杂的安全访问要求,您可能会发现单个存储桶策略将变得难以维护。在这种情况下,您可能有数量较少的存储桶,每个存储桶都有其自己的较小、可管理的安全策略。
大多数客户发现,根据所管理数据的生命周期,他们有不同的安全要求。我们经常看到,客户通过一系列转换来收集数据,然后进行数据传输,这些转换从原始的应用程序格式化的数据,到最终符合业务术语被分析应用使用的数据,就像在企业数据仓库中一样。下面我们讨论一个典型的企业数据仓库分层设计:
数仓的分层建模是在企业数据仓库中数据预处理的常用方式,将原始数据层层计算保存可以帮助我们理清业务数据,避免重复计算增加数据使用便捷性,避免数据分歧。数据湖中的分层定义可以更多样化,多元化映射,例如以下的示例:

您可能会发现,所有数据湖不同阶段数据存放的位置都可以通过前缀进行管理。

我们应仔细设计前缀结构以支持所需的安全和数据分层模型。对于本指南的下面部分,我们将假设您对数据湖中的所有内容都使用单个 S3 存储桶,如上图所示,该存储前缀的第一个字段都是数据管道中的"生命周期阶段"。
在第一个字段的斜线后面,我们应该设计第二个字段,第二字段可以通过数据的所有权进行定义。通常围绕业务单位,因为虽然数据在数据湖中共享,但数据也应该由某人拥有,此字段可以将数据筛选到基于前缀布局和安全模型中。您还应考虑,虽然数据湖支持非结构化和半结构化数据,但 Hadoop 和 Spark 生态系统中的分析和数据分析工具通过数据目录通常希望找到存储在同一位置的类似结构的不同数据。这些相同的工具支持基于数据属性值进行分区,这可以显著提高数据分析用户的易管理性。
对于共享存储桶,数据湖设计前缀层次结构需要因地制宜的进行设计,例如:
您还可以选择在应用程序所有者(如"日志")下或基于应用程序名称为数据收集引入前缀。此外,您可以选择实现架构和数据库的概念高于数据类型级别。在这两种情况下,您都应该认为这些概念基于顶级前缀 (数据生命周期)应用于所有数据,并且此存储策略应在整个系统中强制实施和以便易于管理。
如上所述,对于大型数据集,应实现基于时间的分区。这提供了一个很好的常规导航机制,并减少了访问一组文件之前必须"列出"的数据量。这可显著提高查询用户的性能并降低成本。请考虑一下select * where 和select * 的区别。
下图显示了有分区和没分区的查询效率差距
在几乎所有情况下,您应该在月份级别实现分区,但您也可能发现每日颗粒性更好。对于非常大的数据集,通常只查看最近的数据,可以按小时作进一步分区,但它很少有利于按分钟或秒分区。通过了解通常针对存储位置执行的查询的时间范围,您可以为前缀选择正确的粒度。请记住,无论前缀中的分区结构是什么,您仍将摄取所有数据。它只是意味着您将可能创建更多的文件,这允许您在读取数据时对访问的时间范围更具选择性。
用于基于时间的分区的值的结构非常重要,因为它可以指示数据湖的运行方式。管理这些分区有两种主要方法:
partition attribute=partition value的形式存储分区前缀。例如,订单日期将存储order_date=<SomeDateValue>Jan2019中存储 2019 年 1 月的数据,但如果需要将部分路径做变更,例如将2月的数据存放在2019-02。那么手动发出命令"alter table mytable add partition (month='jan', year='2019') location 's3://mybucket/prefix/Jan2019'; 和 alter table mytable add partition (month='feb', year='2019') location 's3://mybucket/prefix/2019-02';我们强烈建议客户尽可能使用动态分区,因为它大大简化了数据目录的操作。使用此格式时,分区会自动且始终包含在查询中,并且可以使用命令手动添加 msck repair table <mytable>;.
您必须考虑给定数据类型的分区项。有两种主要方法通常用于基于时间的分区,并且与分区的粒度一样,应该根据您认为最终用户希望如何处理数据来决定:
平面分区
故名思义则是将year-month-day看作一个整体。比如说日期2018-12-25,假设分区字段为名为date,那么最终的partition则为’date=2018-12-25。在此模型中,满足分区方案粒度的日期值作为简单字符串存储。字符串几乎可以肯定按顺序格式化YEAR MONTH DAY HOUR,例如"YYYY-MM-DD HH24",以便支持基于字符串的比较,包括仅使用 ASCII 字符正确排序的"之间、大于、小于等"。在这种情况下,您通常会存储完整的日期值,但将其截断到分区的粒度 - ,1970 年1月1日上午 9 点的数据将存储为 1970-01-01 00 (at midnight),同时按每小时粒度被截断。与动态分区结合使用时,这将导致前缀 order_date=1970-01-01 00.
此模型对于最终用户来说可以简单得多,并且他们可以通过目录对单个"DATE"类型属性使用简单的日期表达式
嵌套分区
嵌套分区,是将年(year)、月(month)、日(day)拆开,那么最终的分区结构为三级结构’year=2018/month=12/day=25’
嵌套分区可以在数据目录中实现日期层次结构,而不是使用平面字符串日期。这意味着年、月、日、小时存储为单独的前缀,并建模为目录中的"INT"类型的属性。在这种情况下,您为日期的每个组件有一个单独的前缀。例如,1970 年 1 月 1 日的数据将存储在前缀year=1970/month=01/day=01
此模型为使用不同类型的查询跨多个时间维度查询的最终用户提供了易操作性,例如查询每月的,每周的数据。但对于想要对日期值执行相等操作的最终用户来说,这更为复杂,基于时间的一级分区相比于多级分区能够更好的支持类似like、in、between等SQL语句。

在数据分析的整体工作负载中,除了数据湖,我们还应该考虑其他适当的数据存储位置。
例如OLTP,OLAP,数据湖的不同定义
OLTP (Online Transaction Processing)
具有大量的短事务(INSERT,UPDATE,DELETE)的特征,这些短事务充当应用程序的持久层。例如Aurora,MySQL,PostgreSQL等。通常为行存储架构
OLAP (Online Analytical Processing)
以交易量相对较低为特征,查询通常很复杂,并且涉及针对大型历史数据集的汇总,以进行数据驱动的决策。例如Amazon Redshift,Greenplum等。通常为列存储架构
Data Lake
一种架构范例,允许客户将所有数据存储在一个统一的地方,在这里他们可以以任意规模和低成本收集和存储任何数据。数据湖补充(而不是替代)其他数据存储,例如数据仓库。
我们简单考虑一家航空公司的数据存储位置
对于一个数据分析架构的整体设计,我们应该考虑数据的稳定选择对应的存储位置,AWS提供了多种不同温度层级的数据存储选项,我们应该从整体架构设计角度设计对应的存储位置。例如在有点典型的推荐系统中,我们会将流处理和批处理计算出来的类似商品表(结果表)保存在dynamodb中,以便应用程序可以快速的读取推荐表中的对应数据,低延迟的向最终用户返回推荐信息。
