同时从S3下载多个文件并合并它们

时间:2017-06-26 16:39:23

标签: go aws-sdk aws-sdk-go

我试图同时从S3下载多个文件,并将它们的内容合并到一个字节缓冲区。文件是csv格式的。我的代码似乎大部分时间(10次尝试中有8次)。但是有些实例在我检查了整合缓冲区后,我得到的东西少了我应该得到的(通常不超过缺少100行)。预计的总记录数为4802。 如果按顺序运行我的代码,则不会出现此问题。但是我需要使用goroutines来提高速度。这是我尝试做的一个主要要求。我已经运行了go数据竞赛检查器,没有出现数据竞争,并且出现错误我打印的陈述永远不会打印出来。

这是我使用的代码:

    var pingsBuffer = aws.NewWriteAtBuffer([]byte{}) 
        //range over the contents of the index file
    for _, file := range indexList {
        wg.Add(1)
        go download(key + string(file), pingsBuffer, &wg)
    }
    wg.Wait()

和下载功能(也整合了下载的文件)

func download(key string, buffer *aws.WriteAtBuffer, wg *sync.WaitGroup)  {

defer wg.Done()

awsBuffer := aws.NewWriteAtBuffer([]byte{})

input := &s3.GetObjectInput {
    Bucket: aws.String(defaultLocationRootBucket),
    Key:    aws.String(key),
}

n1, downloadError := downloader.Download(awsBuffer, input)
if downloadError != nil {
    loglib.Log(loglib.LevelError, applicationType, fmt.Sprintf("Failed to download from S3, file(%v) with error : %v.", key, downloadError))
    return
}


lenghts3:= int64(len(buffer.Bytes()))

n2, bufferError := buffer.WriteAt(awsBuffer.Bytes(), lenghts3 )
if bufferError != nil {
    loglib.Log(loglib.LevelError, applicationType, fmt.Sprintf("Failed to write to buffer, the file(%v) downloaded from S3  with error : %v.", key, bufferError))
}

1 个答案:

答案 0 :(得分:0)

此代码:

lenghts3:= int64(len(buffer.Bytes()))

是一个并发问题:两个例程可以同时获得长度,获得相同的起始位置,并且两个例程都继续写入具有相同起始位置的缓冲区,相互踩踏脚趾。 / p>

由于您已经在内存中检索整个对象而没有流式传输到组合缓冲区,您也可以只在一个通道上发送每个文件的全部内容,并在该通道上有一个接收器将每个结果附加到它们是同步进入的共享字节缓冲区。