在Amazon S3上解压缩大型ZIP文件

时间:2015-09-21 14:28:25

标签: amazon-web-services amazon-s3 zip unzip

我在一家处理非常大的CSV文件的公司工作。客户端通过filepicker将文件上载到Amazon S3。然后,多个服务器进程可以并行读取文件(即从不同点开始)以处理它并将其存储在数据库中。可选地,客户端可以在上载之前压缩文件。

  1. 我是否认为ZIP格式不允许并行解压缩单个文件?也就是说,没有办法让多个进程从不同的偏移量读取ZIP文件(可能在块之间有一些重叠)并从那里流出未压缩的数据?
  2. 如果我是正确的,那么我想要一种方法来获取S3上的ZIP文件,并在S3上生成一个解压缩的CSV。

    1. 亚马逊是否提供可以执行此任务的任何服务?我希望Data Pipeline可以完成这项工作,但它似乎有局限性。例如" CopyActivity不支持复制多部分Amazon S3文件" (source)似乎暗示我不能使用它解压缩大于5GB的任何东西。我对数据管道的理解非常有限,所以我不知道它对于这项任务有多适合,或者我的目标。
    2. 是否有任何SaaS可以完成这项工作?
    3. 我可以编写代码来下载,解压缩和分段上传文件回S3,但我希望有一个高效,易于扩展的解决方案。 AWS Lambda非常适合运行代码(以避免配置不需要的资源),但执行时间限制为60秒。此外,用例看起来如此简单和通用,我希望找到一个现有的解决方案。

6 个答案:

答案 0 :(得分:2)

您可以使用lambda触发胶水,该胶水可以下载文件,将文件解压缩并上传回s3,这将是无服务器的

答案 1 :(得分:1)

每次将zip文件上传到S3时,最好将S3事件通知发送到SQS队列,并且有一个或多个EC2实例轮询队列,等待文件解压缩。

您可能只需要在运行的实例上执行此操作,但如果SQS队列的大小变得太大而单个实例无法足够快地执行解压缩,则您还可以使用自动调度策略来旋转更多实例(由你定义。)

答案 2 :(得分:0)

@ E.J。 Brennan是对的,我与AWS支持聊天,他们告诉我们不能使用Lambda来做这个操作。以下是我从支持部门获得的指导。

  • 每当在S3中删除文件时。

  • 触发向SQS发送通知。

  • 让EC3听SQS。

  • 做Un ZIP。

  • 向SQS添加另一个通知,下一个lambda函数可以进行进一步处理。

希望它有所帮助。我浪费了很多时间来解决这个问题,

解决方案/解决方法!!

经过长时间的斗争,我的技术主管得到了解决方案。我们可以使用AWS Glue来解决这个问题。这有更多的内存可供使用。它完成了工作。

希望它有所帮助。

答案 3 :(得分:0)

我正在使用一个没有应用程序的EMR群集,它只有一个节点(只有主节点,没有从节点),并且让它运行一个运行Shell脚本的步骤。

shell脚本执行以下操作:

  1. 将S3中的thezeep.zip文件下载到主节点中的/ mnt文件夹中
  2. 将文件内容解压缩到/ mnt / thezeep /
  3. 将提取的文件上传到S3。

整个过程需要20分钟才能处理一个10Gb的zip文件,其中包含总共100Gb的文件。

该步骤终止后,EMR群集将自动关闭。

N.B。 :缺点是,如果/ mnt /文件夹上没有足够的空间来下载和/或解压缩文件,则该步骤不会单独终止。它将等待,要求您提供无法返回的...,因此您必须手动终止集群...
因此,请不要在EBS卷上添加更多空间来避免此类问题。

答案 4 :(得分:0)

您始终可以将EC2与Active Polling一起使用,但这并不是一个经济高效的解决方案。
还有其他解决方案,例如AWS EMR(弹性地图缩减)或AWS Glue。
但是,最具成本效益的解决方案仍然是using lambda function

您将不会遇到任何存储问题,因为它没有存储任何数据。一切都在进行中。

答案 5 :(得分:0)

完全可以通过一次Lambda调用来处理10GB文件,即使内容在ZIP文件中(尽管Lambda中可用的最大内存为3GB)。使用CSV肯定更容易,因为您可以使用多个Lambda调用通过Range请求同时读取文件的不同部分(如果对象是公共的,则S3在API中以及通过纯HTTP支持此操作)。

我已经编写了一个C#流实现,演示了如何最轻松地完成此操作。该流使用S3 API来获取文件的子集,以便仅将其部分保存在内存中,但提供标准的Stream接口,以便可以使用System.IO.Compression.ZipArchive来读取内容(通常,您需要磁盘上的文件,或者Memory流中的所有内容都可以做到这一点。

Github repo包含一个示例,该示例可以满足您的需要,尽管文件较小(1GB),并且有意用电量不足的lambda(配置为最小内存256MB)。参见./Examples/Process1GBWith256MBLambda。

基本上,您的代码如下所示:

using var stream = new Cppl.Utilities.AWS.SeekableS3Stream(s3, BUCKET, KEY, 12 * 1024 * 1024, 5);
using var zip = new ZipArchive(stream, ZipArchiveMode.Read);
var entry = zip.GetEntry(FILENAME);
using var file = entry.Open();
using var reader = new StreamReader(file);

string line = null;
while ((line  = await reader.ReadLineAsync()) != null) {
   // process line here
}

不需要(通常是空闲的)EC2实例或其他预留容量计费资源。简单的Lambda可以解决问题。而且,正如其他张贴者所提到的那样,在S3事件触发器上触发这样的Lambda将是明智之举。