Самый эффективный способ пакетного удаления файлов S3

16

Я хотел бы иметь возможность пакетного удаления тысяч или десятков тысяч файлов одновременно на S3. Каждый файл будет от 1 до 50 МБ. Естественно, я не хочу, чтобы пользователь (или мой сервер) ждал, пока файлы находятся в процессе удаления. Отсюда и вопросы:

  1. Как S3 обрабатывает удаление файлов, особенно при удалении большого количества файлов?
  2. Есть ли эффективный способ сделать это и заставить AWS выполнять большую часть работы? Под эффективностью я подразумеваю выполнение наименьшего количества запросов к S3 и наименьшее количество времени, используя наименьшее количество ресурсов на моих серверах.
SudoKill
источник

Ответы:

12

AWS поддерживает массовое удаление до 1000 объектов за запрос с помощью S3 REST API и его различных оболочек. Этот метод предполагает, что вы знаете, какие ключи объекта S3 вы хотите удалить (то есть он не предназначен для обработки чего-то вроде политики хранения, файлов, размер которых превышает определенный размер и т. Д.).

API SEST REST может указывать до 1000 файлов, которые должны быть удалены за один запрос, что должно быть быстрее, чем выполнение отдельных запросов. Помните, что каждый запрос является запросом HTTP (то есть TCP). Таким образом, каждый запрос несет накладные расходы. Вам просто нужно знать ключи объектов и создать HTTP-запрос (или использовать оболочку на выбранном вами языке). AWS предоставляет отличную информацию об этой функции и ее использовании . Просто выберите метод, который вам наиболее удобен!

Я предполагаю, что ваш вариант использования подразумевает, что конечные пользователи указывают несколько конкретных файлов, которые нужно удалить одновременно. Вместо того, чтобы запускать задачу, такую ​​как «очистить все объекты, которые ссылаются на файлы изображений» или «очистить все файлы, которые старше определенной даты» (что, я считаю, легко настроить отдельно в S3).

Если это так, вы будете знать ключи, которые нужно удалить. Это также означает, что пользователю понравится больше отзывов в реальном времени о том, был ли их файл успешно удален или нет. Ссылки на точные ключи должны быть очень быстрыми, поскольку S3 был разработан для эффективного масштабирования, несмотря на обработку чрезвычайно большого объема данных.

Если нет, вы можете посмотреть на асинхронные вызовы API. Вы можете прочитать немного о том, как они будут работать в целом из этого поста в блоге или найти, как это сделать на выбранном вами языке. Это позволило бы запросу удаления занять свой собственный поток, а остальная часть кода может выполняться, не заставляя пользователя ждать. Или вы можете разгрузить запрос в очередь. , , Но обе эти опции неоправданно усложняют либо ваш код (асинхронный код может раздражать), либо вашу среду (вам понадобится сервис / демон / контейнер / сервер для обработки очереди. Поэтому я бы по возможности избегал этого сценария.

Изменить: у меня нет репутации, чтобы публиковать более 2 ссылок. Но вы можете увидеть комментарии Amazon о частоте запросов и производительности здесь: http://docs.aws.amazon.com/AmazonS3/latest/dev/request-rate-perf-considerations.html А часто задаваемые вопросы о s3, которые массовое удаление является путь, если это возможно.

Эд д'Аццо
источник
17

Мучительно медленный вариант , s3 rm --recursiveесли вы на самом деле , как ждать.

Параллельный запуск s3 rm --recursiveс различными --includeшаблонами немного быстрее, но все еще тратится много времени на ожидание, поскольку каждый процесс по отдельности выбирает весь список ключей для локального выполнения --includeсопоставления с шаблоном.

Введите массовое удаление.

Я обнаружил, что смог добиться максимальной скорости, удалив 1000 ключей одновременно, используя aws s3api delete-objects.

Вот пример:

cat file-of-keys | xargs -P8 -n1000 bash -c 'aws s3api delete-objects --bucket MY_BUCKET_NAME --delete "Objects=[$(printf "{Key=%s}," "$@")],Quiet=true"' _
  • -P8Вариант на xargsконтрольном параллелизм. В данном случае это восемь, что означает 8 экземпляров из 1000 удалений за раз.
  • -n1000Опция указывает xargsна расслоении 1000 ключей для каждого aws s3api delete-objectsвызова.
  • Удаление ,Quiet=trueили изменение его falseприведет к выбросу ответов сервера.
  • Примечание: _в конце этой командной строки легко пропустить . @VladNikiforov опубликовал отличный комментарий о том, для чего он нужен в комментарии, так что я собираюсь просто дать ссылку на это.

Но как ты получаешь file-of-keys?

Если у вас уже есть список ключей, хорошо для вас. Работа завершена.

Если нет, вот один из способов, я думаю:

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
источник
9
Отличный подход, но я обнаружил, что перечисление ключей было узким местом. Это намного быстрее: aws s3api list-objects --output text --bucket BUCKET --query 'Contents[].[Key]' | pv -l > BUCKET.keys и затем удаление объектов (этого было достаточно, чтобы при выполнении одного параллельного процесса достигнут предел скорости удаления объектов): 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
Вы, вероятно, должны были также подчеркнуть важность _в конце :) Я пропустил это, и затем мне потребовалось много времени, чтобы понять, почему пропущен первый элемент. Дело в том, что bash -cвсе аргументы передаются как позиционные параметры, начиная с $0, а «$ @» обрабатывает только параметры, начиная с $1. Таким образом, подчеркивающий манекен необходим для заполнения позиции $0.
Влад Никифоров
@VladNikiforov Ура, отредактировано.
Antak
3
Одна проблема, с которой я столкнулся при таком подходе (от antak или Влада), состоит в том, что его нелегко возобновить в случае ошибки. Если вы удаляете много ключей (в моем случае это 10M), у вас может быть ошибка сети или ошибка регулирования, которая нарушает это. Чтобы улучшить это, я использовал split -l 1000для разделения файла ключей на 1000 пакетов ключей. Теперь для каждого файла я могу выполнить команду удаления, а затем удалить файл. Если что-то пойдет не так, я могу продолжить.
joelittlejohn
Если вы просто хотите получить список ключей, я бы подумал, aws s3 ls "s3://MY_BUCKET_NAME/SOME_SUB_DIR" | awk '{print $4}'что будет проще, и вы можете добавить, | grepчтобы отфильтровать это оттуда.
Хайден
3

Я был разочарован производительностью веб-консоли для этой задачи. Я обнаружил, что команда CLI AWS делает это хорошо. Например:

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

Для большой файловой иерархии это может занять значительное время. Вы можете установить это в сеансе tmuxили screenсеансе и проверить позже.

dannyman
источник
2
Похоже, aws s3 rm --recursiveкоманда удаляет файлы по отдельности. Хотя это и быстрее, чем веб-консоль, при удалении большого количества файлов это может быть намного быстрее, если массовое удаление
Брэндон
2

Аккуратный трюк использует правила жизненного цикла для обработки удаления для вас. Вы можете поставить правило в очередь, чтобы удалить префикс или объекты, которые вы хотите, и Amazon просто позаботится об удалении.

https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-lifecycle.html

cam8001
источник
Будьте осторожны, так как это может быть очень дорого, если у вас много объектов, stackoverflow.com/questions/54255990/…
будет
0

Не зная, как вы управляете корзинами s3, это может быть или не быть особенно полезным.

Инструменты AWS CLI имеют опцию «sync», которая может быть особенно эффективной для обеспечения правильности объектов в s3. Если вы или ваши пользователи управляете S3 из локальной файловой системы, вы можете сэкономить массу работы, определяя, какие объекты необходимо удалить с помощью инструментов CLI.

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

Билл Б
источник
0

Там уже упоминалось о s3 syncкоманде раньше, но без примера и слова о --deleteварианте.

Я нашел самый быстрый способ удалить содержимое папки в S3корзине my_bucket:

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

Hubbitus
источник