我相信 Hadoop 的一个常见使用模式是通过加载来自操作系统的数据的常规(例如每日)快照来构建一个“数据湖”。对于许多系统,每天的变化率通常小于 5% 的行(即使更新了一行,也只有少数字段可能发生变化)。
Q:这样的历史数据如何在HDFS上结构化,既节省空间,又高效访问。
当然,答案将取决于通常如何访问数据。在我们的 Hadoop 集群上:
- 大多数作业只读取和处理最新版本的数据
- 少数作业处理一段时间的历史数据(例如 1 - 3 个月)
- 一些作业处理所有可用的历史数据
这意味着,尽管保留历史数据很重要,但不应该以严重减缓那些只想知道昨天收盘时数据的情况的工作为代价。
我知道一些选项,但似乎都不太令人满意:
将每个完整转储独立存储为新的子目录。这是最明显的设计,简单,并且与 MapReduce 范式非常兼容。我确信有些人使用这种方法,但我想知道他们如何证明存储成本是合理的?假设每天加载 1Tb,那么每年向集群添加 365Tb,其中大部分是重复数据。我知道现在磁盘很便宜,但大多数预算制定者习惯于基础设施与业务增长成比例地扩展,而不是随着时间的推移线性增长。
仅存储与前一天的差异(增量)。当源系统更喜欢以增量形式发送更新时,这是一个自然的选择(这种思维方式似乎可以追溯到数据以 CD-ROM 形式在系统之间传递的时间)。它更节省空间,但更难正确处理(例如,你如何表示删除?),更糟糕的是,它意味着消费者需要扫描整个历史,“事件溯源”式,才能到达在系统的当前状态。
将行的每个版本存储一次,并带有开始和结束日期。这种模式被称为“时变数据”等术语,在数据仓库中非常频繁地出现,并且在需要存储历史值时更普遍地出现在关系数据库设计中。当一行发生变化时,更新以前的版本以设置“结束日期”,然后插入以今天为“开始日期”的新版本。不幸的是,这并不能很好地转化为 Hadoop 范式,在这种范式中,只支持追加数据集,并且没有更新行的原生概念(尽管可以通过覆盖现有数据文件来实现该效果)。这种方法需要相当复杂的逻辑来加载数据,但不可否认的是,使用这种结构来消费数据非常方便。
(值得注意的是,每天都在变化一个特别不稳定的字段,以使后一个选项降级到与选项 1 相同的空间效率)。
那么......是否还有另一种将空间效率与易用性相结合的选择?