使用 AWS Firehose 时连接 s3 文件

Posted

技术标签:

【中文标题】使用 AWS Firehose 时连接 s3 文件【英文标题】:Concatenate s3 files when using AWS Firehose 【发布时间】:2016-08-23 14:31:11 【问题描述】:

我有一个AWS Kinesis Firehose 流将数据放入 s3 中,配置如下:

S3 buffer size (MB)*       2
S3 buffer interval (sec)*  60

一切正常。唯一的问题是 Firehose 为每个数据块创建一个 s3 文件。 (在我的情况下,每分钟一个文件,如屏幕截图所示)。随着时间的推移,这是很多文件:每天 1440 个文件,每年 525k 个文件。

这很难管理(例如,如果我想将存储桶复制到另一个存储桶,我需要一个一个地复制每个文件,这需要时间)。

两个问题:

有没有办法告诉 Kinesis 将旧文件组合/连接在一起。 (例如,超过 24 小时的文件每天被分组为一个块)。 当COPYing 来自大量 s3 文件而不是少数几个时,COPY redshift 性能有何影响?我没有精确地测量过这个,但根据我的经验,很多小文件的性能要差得多。据我所知,使用大文件时,大约 2M 行的 COPY 大约需要 1 分钟。 2M 行包含大量小文件(约 11k 文件),最多需要 30 分钟。

我的两个主要担忧是:

更好的红移 COPY 性能(来自 s3) 更轻松的整体 s3 文件管理(备份、任何类型的操作)

【问题讨论】:

【参考方案1】:

对您来说最简单的解决方法是增加 firehose 缓冲区大小和时间限制 - 您最多可以延长 15 分钟,这会将每天 1440 个文件减少到每天 96 个文件(除非您达到文件大小当然是限制)。

除此之外,Kinesis 中没有任何内容可以为您连接文件,但您可以设置一个 S3 生命周期事件,该事件在每次创建新的 Kinesis 文件时触发并向其中添加一些您自己的代码(可能在 EC2 上运行或使用 Lambda 实现无服务器)并自己进行连接。

无法评论红移加载性能,但我怀疑这不是什么大不了的事,如果它是 - 或将成为一个,我怀疑 AWS 会对性能做一些事情,因为这是他们设置的使用模式。

【讨论】:

【参考方案2】:

Kinesis Firehose 旨在实现近乎实时的事件处理。它针对此类用例进行了优化,因此您可以将文件设置为更小、更频繁的文件。通过这种方式,您可以更快地获取 Redshift 中的查询数据,或者更频繁地在较小文件上调用 Lambda 函数。

该服务的客户还为更长的历史查询准备数据是很常见的。即使可以在 Redshift 上运行这些长期查询,对这些查询使用 EMR 也可能有意义。然后,您可以针对最近更受欢迎的事件调整您的 Redshift 集群(例如,SSD 上的“热”集群 3 个月,HDD 上的“冷”集群 1 年)。

您将在 Firehose 输出 S3 存储桶中获取较小的(未压缩?)文件并将它们传输到更 EMR (Hadoop/Spark/Presto) 优化的格式是有道理的。您可以使用诸如S3DistCp 之类的服务,或类似的功能,将较小的文件连接起来并将其格式转换为Parquet 格式。

关于 Redshift COPY 的优化,在聚合事件的时间和复制它们所需的时间之间存在平衡。确实,当您复制到 Redshift 时,最好有更大的文件,因为每个文件的开销很小。但另一方面,如果您仅每 15 分钟复制一次数据,您可能会遇到“安静”的时间,即您没有利用网络或集群在这些 COPY 命令之间摄取事件的能力。您应该找到对业务有利的平衡点(您需要多新鲜的事件)和技术方面(您可以在一小时/天内将多少事件摄取到 Redshift)。

【讨论】:

【参考方案3】:

我遇到了类似的问题,文件数量太多而无法处理。这是一个有用的解决方案:

i) 将大小缓冲区增加到最大值。 (128 MB)

ii) 将时间缓冲增加到最大值。 (900 秒)

iii) 与其一次发布一条记录,不如将多条记录合并为一条(用一条线分隔),以制作一条 kinesis firehose 记录(KF 记录的最大大小为:1000 KB)。

iv) 此外,将多个 kinesis firehose 记录组合成一个批次,然后进行批次放置。 (http://docs.aws.amazon.com/firehose/latest/APIReference/API_PutRecordBatch.html)

这将使一个 s3 对象发布为:kinesis firehose 流可以容纳的批次数。

希望这会有所帮助。

【讨论】:

是的。不幸的是,就我而言,我希望记录能够快速交付。我不能等待 900 秒,因为我想要半实时的新数据。所以我正在考虑一种解决方案,将所有数据加载到 redshift 中,然后在一个(或几个)s3 文件中一次卸载所有数据。 另一个适合用例的想法:i) 在您的 S3 存储桶上设置 AWS Lambda。 ii) 根据您的需要保留 AWS kinesis firehose 流设置。 iii)因此,如问题所述,文件过多。 iv) 现在,每当有发布到存储桶时,Lambda 函数都应该触发,将多个文件合并为一个并将其放入不同的存储桶中。如果您不想将其放入不同的存储桶中,则可以将其放入具有不同前缀的相同存储桶中,这样它就不会再次触发 lambda 函数。这样会更简单。

以上是关于使用 AWS Firehose 时连接 s3 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 AWS kinesis-firehose 将数据写入文件

AWS Firehose中间S3存储桶和传输流依赖关系出现问题

将镶木地板从 AWS Kinesis firehose 写入 AWS S3

AWS Firehose 到 S3 的内容前缀

将AWS Kinesis Firehose回填到Elasticsearch Service失败的记录

Kinesis Firehose-什么是S3扩展目标配置?