A maneira mais eficiente de excluir em lote arquivos S3

16

Eu gostaria de poder excluir em lote milhares ou dezenas de milhares de arquivos por vez no S3. Cada arquivo pode ter entre 1 e 50 MB. Naturalmente, não quero que o usuário (ou meu servidor) aguarde enquanto os arquivos estão sendo excluídos. Portanto, as perguntas:

  1. Como o S3 lida com a exclusão de arquivos, especialmente ao excluir um grande número de arquivos?
  2. Existe uma maneira eficiente de fazer isso e fazer com que a AWS faça a maior parte do trabalho? Por eficiente, quero dizer, fazer o menor número de solicitações para o S3 e gastar menos tempo usando a menor quantidade de recursos em meus servidores.
SudoKill
fonte

Respostas:

12

A AWS oferece suporte à exclusão em massa de até 1000 objetos por solicitação usando a API REST S3 e seus vários wrappers. Este método pressupõe que você conhece as chaves de objeto do S3 que deseja remover (ou seja, não foi projetado para lidar com algo como uma política de retenção, arquivos com mais de um determinado tamanho etc.).

A API REST S3 pode especificar até 1000 arquivos a serem excluídos em uma única solicitação, o que deve ser mais rápido que fazer solicitações individuais. Lembre-se, cada solicitação é uma solicitação HTTP (portanto, TCP). Portanto, cada solicitação é sobrecarregada. Você só precisa conhecer as chaves dos objetos e criar uma solicitação HTTP (ou usar um wrapper no seu idioma preferido). A AWS fornece ótimas informações sobre esse recurso e seu uso . Basta escolher o método com o qual você se sente mais confortável!

Suponho que o seu caso de uso envolva usuários finais especificando vários arquivos específicos para excluir ao mesmo tempo. Em vez de iniciar uma tarefa como "limpar todos os objetos que se referem a arquivos de imagem" ou "limpar todos os arquivos anteriores a uma determinada data" (que eu acredito que seja fácil de configurar separadamente no S3).

Nesse caso, você saberá as chaves que precisa excluir. Isso também significa que o usuário receberá mais feedback em tempo real sobre se o arquivo foi excluído ou não com sucesso. As referências às chaves exatas devem ser muito rápidas, pois o S3 foi projetado para ser dimensionado com eficiência, apesar de lidar com uma quantidade extremamente grande de dados.

Caso contrário, você pode procurar chamadas de API assíncronas. Você pode ler um pouco sobre como eles funcionariam em geral nesta postagem do blog ou procurar como fazê-lo no idioma de sua escolha. Isso permitiria que a solicitação de exclusão ocupasse seu próprio encadeamento, e o restante do código pode ser executado sem fazer o usuário esperar. Ou, você pode transferir a solicitação para uma fila. . . Mas essas duas opções complicam desnecessariamente o seu código (o código assíncrono pode ser irritante) ou o seu ambiente (você precisaria de um serviço / daemon / container / servidor para lidar com a fila. Portanto, evitaria esse cenário, se possível.

Editar: não tenho reputação de postar mais de 2 links. Mas você pode ver os comentários da Amazon sobre taxa de solicitação e desempenho aqui: http://docs.aws.amazon.com/AmazonS3/latest/dev/request-rate-perf-considerations.html E o FAQ do s3 comenta que o deleiton em massa é o caminho a percorrer, se possível.

Ed D'Azzo
fonte
17

A opção terrivelmente lenta é s3 rm --recursivese você realmente gosta de esperar.

A execução paralela s3 rm --recursivea diferentes --includepadrões é um pouco mais rápida, mas ainda é gasto muito tempo aguardando, pois cada processo busca individualmente toda a lista de chaves para executar localmente a --includecorrespondência de padrões.

Digite a exclusão em massa.

Eu descobri que era capaz de obter o máximo de velocidade ao excluir 1000 chaves por vez usando aws s3api delete-objects.

Aqui está um exemplo:

cat file-of-keys | xargs -P8 -n1000 bash -c 'aws s3api delete-objects --bucket MY_BUCKET_NAME --delete "Objects=[$(printf "{Key=%s}," "$@")],Quiet=true"' _
  • A -P8opção on xargscontrola o paralelismo. São oito neste caso, o que significa oito instâncias de 1000 exclusões por vez.
  • A -n1000opção informa xargspara agrupar 1000 teclas para cada aws s3api delete-objectschamada.
  • Removê-lo ,Quiet=trueou alterá-lo para falsevomitar respostas do servidor.
  • Nota: Há uma falha facilmente perdida _no final dessa linha de comando. O @VladNikiforov postou um excelente comentário sobre o que é no comentário, então eu vou apenas ligar para isso.

Mas como você consegue file-of-keys?

Se você já possui sua lista de chaves, é bom para você. Trabalho concluído.

Se não, aqui está uma maneira, eu acho:

aws s3 ls "s3://MY_BUCKET_NAME/SOME_SUB_DIR" | sed -nre "s|[0-9-]+ [0-9:]+ +[0-9]+ |SOME_SUB_DIR|p" >file-of-keys
Antak
fonte
9
Ótima abordagem, mas achei que listar as chaves era o gargalo. Isso é muito mais rápido: aws s3api list-objects --output text --bucket BUCKET --query 'Contents[].[Key]' | pv -l > BUCKET.keys e, em seguida, removendo objetos (bastava que um processo paralelo atingisse os limites de taxa para exclusão de objetos): tail -n+0 BUCKET.keys | pv -l | grep -v -e "'" | tr '\n' '\0' | xargs -0 -P1 -n1000 bash -c 'aws s3api delete-objects --bucket BUCKET --delete "Objects=[$(printf "{Key=%q}," "$@")],Quiet=true"' _
SEK
2
Você provavelmente também deveria ter enfatizado a importância no _final :) Perdi e demorei um pouco para entender por que o primeiro elemento foi ignorado. O ponto é que bash -cpassa todos os argumentos como parâmetros posicionais, começando com $0, enquanto "$ @" processa apenas parâmetros começando com $1. Portanto, o manequim de sublinhado é necessário para preencher a posição de $0.
Vlad Nikiforov
@VladNikiforov Cheers, editado.
antak
3
Um problema que encontrei com essa abordagem (da antak ou da Vlad) é que não é facilmente recuperável se houver um erro. Se você estiver excluindo muitas chaves (10 milhões no meu caso), poderá ter um erro de rede ou de limitação que interrompe isso. Então, para melhorar isso, eu costumava split -l 1000dividir meu arquivo de chaves em 1000 lotes de chaves. Agora, para cada arquivo, posso emitir o comando delete e excluir o arquivo. Se algo der errado, eu posso continuar.
Joelittlejohn
Se você quiser apenas uma lista de chaves, eu acho aws s3 ls "s3://MY_BUCKET_NAME/SOME_SUB_DIR" | awk '{print $4}'que seria mais simples e você pode adicionar um | greppara filtrar isso a partir daí.
Hayden
3

Fiquei frustrado com o desempenho do console da web para esta tarefa. Eu descobri que o comando da AWS CLI faz isso bem. Por exemplo:

aws s3 rm --recursive s3://my-bucket-name/huge-directory-full-of-files

Para uma hierarquia de arquivos grandes, isso pode levar uma quantidade considerável de tempo. Você pode configurá-lo em uma sessão tmuxou screene verificar mais tarde.

dannyman
fonte
2
Parece que o aws s3 rm --recursivecomando exclui arquivos individualmente. Embora mais rápido do que o console da web, ao excluir lotes de arquivos, poderia ser muito mais rápido se excluída a granel
Brandon
0

Sem saber como você está gerenciando os buckets s3, isso pode ou não ser particularmente útil.

As ferramentas da CLI da AWS têm uma opção chamada "sincronização", que pode ser particularmente eficaz para garantir que o s3 tenha os objetos corretos. Se você ou seus usuários estiverem gerenciando o S3 a partir de um sistema de arquivos local, poderá economizar muito trabalho determinando quais objetos precisam ser excluídos usando as ferramentas da CLI.

http://docs.aws.amazon.com/cli/latest/reference/s3/sync.html

Bill B
fonte
0

Já mencionamos o s3 synccomando antes, mas sem exemplo e palavra sobre a --deleteopção.

Eu achei a maneira mais rápida de excluir o conteúdo da pasta no S3bucket my_bucket:

aws s3 sync --delete "local-empty-dir/" "s3://my_bucket/path-to-clear"

Hubbitus
fonte