首页 > 解决方案 > 最高效的 HDFS 数据存储格式

问题描述

我必须在 HDFS 的专用存储服务器上存储大量数据。这是某种历史数据的存档。存储的数据是面向行的,并且有数十种不同类型的字段。其中一些是字符串,一些是整数,还有一些浮点数、短裤、数组列表和地图。

这个想法是使用 MapReduce 或 Spark 作业不时扫描数据。

目前我将它们存储为 SequenceFiles,其中 NullWritable 作为键,自定义 WritableComparable 类作为值。这个自定义类定义了所有这些字段。

我想实现两个目标 - 一个是优化数据大小,因为它变得非常大,我必须每隔几周添加新服务器,成本不断增长。另一件事是更容易添加新字段 - 在当前状态下,如果我想添加一些新字段,我将不得不重写所有旧数据。

我试图通过在这个类中使用 EnumMap 来实现这一点。它给出了相当不错的结果,因为它可以轻松添加新字段,并且数据大小减少了 20%(原因是记录中的很多字段通常是空的)。但是我写的代码看起来很糟糕,当我尝试将列表和地图添加到这个 EnumMap 时,它变得更加丑陋。相同类型的数据没问题,但尝试组合所有字段是一场噩梦。

所以我想到了一些其他流行的格式。我尝试过 Avro 和 Parquet,但在尝试使用 Enums 之前,数据的大小几乎与使用自定义类的 SequenceFiles 完全相同。所以它解决了添加新字段而不需要重写旧数据的问题,但我觉得优化数据大小的潜力更大。

我还要检查的另一件事当然是加载数据所需的时间(这也会告诉我是否可以使用 bzip2 压缩,或者由于性能原因我必须回到 gzip),但在我之前继续这个我想知道是否有人会提出其他解决方案或提示。

提前感谢所有评论。

标签: hadoophdfsstorageavrosequencefile

解决方案


您的大多数方法似乎都不错。我只是决定在这个答案中添加一些我的想法。

存储的数据是面向行的,并且有数十种不同类型的字段。其中一些是字符串,一些是整数,还有一些浮点数、短裤、数组列表和地图。

您在这里提到的所有类型都没有比spark 支持的数据类型更复杂。所以我不会以任何方式更改数据类型。

实现两个目标 - 一个是优化数据大小,因为它变得非常大,我必须每隔几周添加新服务器,并且成本不断增长。

通过添加服务器,您是否也在添加计算?存储应该相对便宜,我想知道您是否正在为您的服务器添加计算,而您并不真正需要。您应该只为存储和检索数据付费。考虑一个像 S3 这样的简单对象存储,它只向您收取存储空间的费用,并提供免费的访问请求配额(GET/PUT/POST)——我相信大约有 1000 个请求是免费的,每月 1 TB 的存储成本仅为 10 美元.

另一件事是更容易添加新字段 - 在当前状态下,如果我想添加一些新字段,我将不得不重写所有旧数据。

如果您有一个用例,您将更频繁地写入文件而不是读取,我建议不要将文件存储在 HDFS 上。它更适合一次写入,多次读取类型的应用程序。也就是说,我建议使用 parquet 开始,因为我认为您将需要一种允许对数据进行切片和切块的文件格式。Avro 也是一个不错的选择,因为它还支持模式演化。但是,如果您有一个复杂的结构,您需要指定架构并使其更容易使用 java 对象进行序列化/反序列化,则最好使用它。

我还要检查的另一件事当然是加载数据所需的时间(这也会告诉我是否可以使用 bzip2 压缩,或者由于性能原因我必须回到 gzip)

Bzip2 的压缩率最高,但也是最慢的。因此,如果数据没有真正经常使用/查询,我会推荐它。Gzip 具有与 Bzip2 相当的压缩率,但速度稍快。还要考虑 snappy 压缩,因为它具有性能和存储的平衡,并且可以支持某些文件类型(parquet 或 avro)的可拆分文件,这对于 map-reduce 作业很有用。


推荐阅读