La forma más eficiente de eliminar por lotes los archivos S3

16

Me gustaría poder eliminar por lotes miles o decenas de miles de archivos a la vez en S3. Cada archivo tendría entre 1 MB y 50 MB. Naturalmente, no quiero que el usuario (o mi servidor) esté esperando mientras los archivos están en proceso de eliminación. Por lo tanto, las preguntas:

  1. ¿Cómo maneja S3 la eliminación de archivos, especialmente al eliminar grandes cantidades de archivos?
  2. ¿Existe una manera eficiente de hacer esto y hacer que AWS haga la mayor parte del trabajo? Por eficiente, me refiero a hacer la menor cantidad de solicitudes a S3 y tomar la menor cantidad de tiempo usando la menor cantidad de recursos en mis servidores.
SudoKill
fuente

Respuestas:

12

AWS admite la eliminación masiva de hasta 1000 objetos por solicitud utilizando la API REST de S3 y sus diversos contenedores. Este método supone que conoce las claves de objeto S3 que desea eliminar (es decir, no está diseñado para manejar algo como una política de retención, archivos que tienen un tamaño determinado, etc.).

La API REST de S3 puede especificar que se eliminen hasta 1000 archivos en una sola solicitud, lo que debe ser más rápido que realizar solicitudes individuales. Recuerde, cada solicitud es una solicitud HTTP (por lo tanto, TCP). Entonces cada solicitud lleva gastos generales. Solo necesita conocer las claves de los objetos y crear una solicitud HTTP (o usar un contenedor en el idioma que elija). AWS proporciona gran información sobre esta función y su uso . ¡Simplemente elija el método con el que se sienta más cómodo!

Supongo que su caso de uso implica que los usuarios finales especifiquen una cantidad de archivos específicos para eliminar de una vez. En lugar de iniciar una tarea como "purgar todos los objetos que se refieren a archivos de imágenes" o "purgar todos los archivos anteriores a una fecha determinada" (que creo que es fácil de configurar por separado en S3).

Si es así, conocerá las claves que necesita eliminar. También significa que al usuario le gustará recibir más comentarios en tiempo real sobre si su archivo se eliminó con éxito o no. Se supone que las referencias a claves exactas son muy rápidas, ya que S3 fue diseñado para escalar eficientemente a pesar de manejar una cantidad extremadamente grande de datos.

Si no, puede buscar llamadas API asíncronas. Puedes leer un poco sobre cómo funcionarían en general en esta publicación de blog o buscar cómo hacerlo en el idioma que elijas. Esto permitiría que la solicitud de eliminación tome su propio hilo, y el resto del código puede ejecutarse sin hacer que un usuario espere. O bien, puede descargar la solicitud a una cola. . . Pero ambas opciones complican innecesariamente su código (el código asincrónico puede ser molesto) o su entorno (necesitaría un servicio / demonio / contenedor / servidor para manejar la cola. Así que evitaría este escenario si es posible).

Editar: no tengo la reputación de publicar más de 2 enlaces. Pero puede ver los comentarios de Amazon sobre la tasa de solicitud y el rendimiento aquí: http://docs.aws.amazon.com/AmazonS3/latest/dev/request-rate-perf-considerations.html Y el faq s3 comenta que la eliminación masiva es la camino a seguir si es posible.

Ed D'Azzo
fuente
17

La opción insoportablemente lenta es s3 rm --recursivesi realmente te gusta esperar.

La ejecución paralela s3 rm --recursivecon --includepatrones diferentes es un poco más rápida, pero todavía se pasa mucho tiempo esperando, ya que cada proceso recupera individualmente la lista de claves completa para realizar localmente la --includecoincidencia de patrones.

Ingrese eliminación masiva.

Descubrí que podía obtener la mayor velocidad al eliminar 1000 claves a la vez usando aws s3api delete-objects.

Aquí hay un ejemplo:

cat file-of-keys | xargs -P8 -n1000 bash -c 'aws s3api delete-objects --bucket MY_BUCKET_NAME --delete "Objects=[$(printf "{Key=%s}," "$@")],Quiet=true"' _
  • La -P8opción en xargscontrola el paralelismo. En este caso, son ocho, lo que significa 8 instancias de 1000 eliminaciones a la vez.
  • La -n1000opción indica xargsagrupar 1000 claves para cada aws s3api delete-objectsllamada.
  • Eliminarlo ,Quiet=trueo cambiarlo a falsearrojará respuestas del servidor.
  • Nota: Hay un error que se pierde fácilmente _al final de esa línea de comando. @VladNikiforov publicó un excelente comentario de para qué sirve en el comentario, así que voy a vincularlo.

Pero como llegas file-of-keys?

Si ya tiene su lista de claves, bien por usted. Trabajo completo

Si no, aquí hay una forma, supongo:

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
fuente
99
Gran enfoque, pero encontré que enumerar las claves era el cuello de botella. Esto es mucho más rápido: aws s3api list-objects --output text --bucket BUCKET --query 'Contents[].[Key]' | pv -l > BUCKET.keys y luego eliminar objetos (esto fue suficiente para que al pasar 1 proceso paralelo alcance los límites de velocidad para la eliminación 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
Probablemente también debiste haber enfatizado la importancia _al final :) Me lo perdí y luego me llevó bastante tiempo entender por qué se omite el primer elemento. El punto es que bash -cpasa todos los argumentos como parámetros posicionales, comenzando con $0, mientras que "$ @" solo procesa parámetros que comienzan con $1. Por lo tanto, se necesita el guión bajo para llenar la posición de $0.
Vlad Nikiforov
@VladNikiforov Cheers, editado.
antak
3
Un problema que he encontrado con este enfoque (ya sea de antak o Vlad) es que no es fácilmente reanudable si hay un error. Si está eliminando muchas claves (10M en mi caso) puede tener un error de red, o un error de aceleración, que lo rompe. Para mejorar esto, solía split -l 1000dividir mi archivo de claves en 1000 lotes de claves. Ahora para cada archivo puedo emitir el comando de eliminar y luego eliminar el archivo. Si algo sale mal, puedo continuar.
joelittlejohn
Si solo desea una lista de las claves, creo aws s3 ls "s3://MY_BUCKET_NAME/SOME_SUB_DIR" | awk '{print $4}'que sería más simple y puede agregar una | greppara filtrar eso desde allí.
Hayden
3

Estaba frustrado por el rendimiento de la consola web para esta tarea. Descubrí que el comando AWS CLI hace esto bien. Por ejemplo:

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

Para una jerarquía de archivos grande, esto puede llevar una cantidad considerable de tiempo. Puede configurar esto en una sesión tmuxo screensesión y volver más tarde.

dannyman
fuente
2
Parece que el aws s3 rm --recursivecomando elimina archivos individualmente. Aunque es más rápido que la consola web, al eliminar muchos archivos, podría ser mucho más rápido si se elimina de forma masiva
Brandon
0

Sin saber cómo está administrando los buckets de s3, esto puede o no ser particularmente útil.

Las herramientas de AWS CLI tienen una opción llamada "sincronización" que puede ser particularmente efectiva para garantizar que s3 tenga los objetos correctos. Si usted o sus usuarios administran S3 desde un sistema de archivos local, es posible que pueda ahorrar una tonelada de trabajo para determinar qué objetos deben eliminarse utilizando las herramientas CLI.

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

Bill B
fuente
0

Ya se mencionó sobre el s3 synccomando antes, pero sin ejemplo y palabra sobre la --deleteopción.

Encontré la forma más rápida de eliminar el contenido de la carpeta en el S3cubo my_bucketpor:

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

Hubbitus
fuente