在Hadoop HDFS中高效地存储每日转储

在Hadoop HDFS中高效地存储每日转储,hadoop,delta,datadesign,bigdata,Hadoop,Delta,Datadesign,Bigdata,我认为Hadoop的一种常见使用模式是通过从操作系统加载定期(例如每天)数据快照来构建“数据湖”。对于许多系统,每天的更改率通常小于行的5%(即使更新了行,也只有少数字段可能会更改) Q:如何在HDFS上构建这样的历史数据,使其既节省空间又能高效访问。 当然,答案将取决于数据的访问方式。在我们的Hadoop集群上: 大多数作业仅读取和处理最新版本的数据 一些作业处理一段时间的历史数据(例如1-3个月) 一些作业处理所有可用的历史数据 这意味着,虽然保留历史数据很重要,但它不应该以严重放缓那些

我认为Hadoop的一种常见使用模式是通过从操作系统加载定期(例如每天)数据快照来构建“数据湖”。对于许多系统,每天的更改率通常小于行的5%(即使更新了行,也只有少数字段可能会更改)

Q:如何在HDFS上构建这样的历史数据,使其既节省空间又能高效访问。

当然,答案将取决于数据的访问方式。在我们的Hadoop集群上:

  • 大多数作业仅读取和处理最新版本的数据
  • 一些作业处理一段时间的历史数据(例如1-3个月)
  • 一些作业处理所有可用的历史数据
这意味着,虽然保留历史数据很重要,但它不应该以严重放缓那些只想知道昨天业务结束时数据的工作为代价

我知道有几个选择,但没有一个是令人满意的:

  • 将每个完整转储单独存储为一个新的子目录。这是最明显的设计,简单,并且与MapReduce范例非常兼容。我相信有些人会使用这种方法,但我想知道他们如何证明存储成本的合理性?假设每天加载1Tb的数据,则每年会向集群中添加365Tb的重复数据。我知道现在磁盘很便宜,但大多数预算制定者习惯于基础设施的扩展与业务增长成比例,而不是随时间线性增长

  • 只存储与前一天的差异(增量)。当源系统喜欢以增量的形式发送更新时,这是一个自然的选择(这种心态似乎始于系统之间以CD-ROM的形式传递数据时)。它更节省空间,但更难做到正确(例如,您如何表示删除?),更糟糕的是,它意味着消费者需要扫描整个历史,“事件来源”式,以达到系统的当前状态

  • 将行的每个版本存储一次,并带有开始日期和结束日期。以“时变数据”等术语著称,这种模式在数据仓库中非常常见,在关系数据库设计中,当需要存储历史值时,会更普遍地出现。当一行发生更改时,更新以前的版本以设置“结束日期”,然后插入新版本,以今天作为“开始日期”。不幸的是,这并不能很好地转化为Hadoop范例,在Hadoop范例中,只附加数据集是受欢迎的,并且没有更新行的本机概念(尽管这种效果可以通过覆盖现有数据文件来实现)。这种方法需要相当复杂的逻辑来加载数据,但无可否认,使用这种结构使用数据是非常方便的

  • (值得注意的是,只需每天更换一个特别不稳定的字段,即可使后一个选项降低到与选项1相同的空间效率)


    那么…有没有另一个结合了空间效率和易用性的选项?

    我建议使用选项3的一个变体,它尊重HDFS的仅附加特性

    我们保留两个数据集,而不是一个数据集,其中包含不同类型的信息,分别存储:

  • 过期行的历史记录,很可能按结束日期(可能是每月)进行分区。只有当知道行的结束日期时,才会向其添加行
  • 特定日期(至少包括最近一天)的快照集合,很可能按快照日期进行分区。每天可以添加新快照,几天后可以删除旧快照,因为它们可以从当前快照和过期记录的历史记录中重建
  • 与选项3的不同之处在于,我们认为未过期的行是与过期的不同类型的信息。 赞成:与HDFS的仅附加特性一致

    赞成:使用当前快照的查询可以在添加新的一天时安全运行,只要我们将快照保留几天(比运行最长查询所需的时间更长)

    赞成:使用历史记录的查询同样可以安全运行,只要它们在最新的“结束日期”上显式地给出一个界限,该界限排除了在运行过程中随后添加的过期行

    缺点:这不仅仅是每天简单的“更新”或“覆盖”。在HDFS的实践中,这通常需要通过复制和过滤来实现,所以这不是一个真正的缺点

    缺点:许多查询需要合并这两个数据集。为了简化这一点,我们可以创建视图或类似视图,将两者适当地结合起来,以生成与选项3完全相同的内容

    缺点:查找最新快照需要找到正确的分区。这可以通过在每次有新快照可用时“滚动”到最新快照的视图来缓解