Удалите огромное количество файлов в Rackspace, используя туман

У меня есть миллионы файлов в Rackspace Files. Я хотел бы удалить часть из них, передав списки имен файлов, а не удалять один за другим, что очень медленно. Есть ли способ сделать это с туманом? Прямо сейчас у меня есть сценарий для удаления каждого файла, но было бы неплохо иметь что-то с лучшей производительностью.

connection = Fog::Storage.new({
 :provider => 'Rackspace',
 :rackspace_username => "xxxx",
 :rackspace_api_key => "xxxx",
 :rackspace_region => :iad 
})

dir = connection.directories.select {|d| d.key == "my_directory"}.first

CloudFileModel.where(duplicated: 1).each do |record| 
 f = record.file.gsub("/","")
 dir.files.destroy(f) rescue nil
 puts "deleted #{record.id}"
end
2 ответа

Да, вы можете с delete_multiple_objects.

Удаляет несколько объектов или контейнеров с одним запросом.

Чтобы удалить объекты из одного контейнера, container может быть предоставлен, а object_names должен быть массивом имен объектов в контейнере.

Чтобы удалить объекты из нескольких контейнеров или удалить контейнеры, container должен быть равен nil и все object_names должны иметь префикс имени контейнера.

Контейнеры должны быть пустыми при удалении. object_names обрабатываются в указанном порядке, поэтому объекты в контейнере должны быть перечислены первыми, чтобы очистить контейнер.

В одном запросе может быть удалено до 10 000 объектов. Для всех запросов сервер ответит 200 OK. response.body должен быть проверен на предмет фактических результатов.

Примеры: удаление объектов из контейнера

object_names = ['object', 'another/object']
conn.delete_multiple_objects('my_container', object_names)

Удаление объектов из нескольких контейнеров

object_names = ['container_a/object', 'container_b/object']
conn.delete_multiple_objects(nil, object_names)

Удалить контейнер и все его объекты

object_names = ['my_container/object_a', 'my_container/object_b', 'my_container']
conn.delete_multiple_objects(nil, object_names)


Насколько мне известно, алгоритм, включенный здесь, является самым надежным и высокопроизводительным алгоритмом для удаления контейнера облачных файлов вместе с любыми объектами, которые он содержит. Алгоритм может быть изменен для ваших целей путем включения параметра с именами элементов для удаления вместо вызова ListObjects. На момент написания этой статьи не существует функциональности на стороне сервера (например, объемной операции), способной своевременно удовлетворить ваши потребности. Массовые операции ограничены 2-3 операциями удаления в секунду, поэтому по меньшей мере 55 минут на 10000 единиц, которые вы удаляете.

Следующий код показывает базовый алгоритм (немного упрощенный из синтаксиса, который действительно требуется в.NET SDK). Он предполагает, что никакие другие клиенты не добавляют объекты в контейнер в любой момент после запуска этого метода.

Обратите внимание, что вы будете ограничены скоростью до 100 операций удаления в секунду для каждого контейнера, который содержит файлы. Если задействовано несколько контейнеров, распределите свои параллельные запросы для округления запросов к каждому из контейнеров. Отрегулируйте уровень параллелизма до значения, которое приближается к пределу жесткой ставки. Использование этого алгоритма позволило мне достичь длительных длительных степеней удаления более 450 объектов в секунду, когда были задействованы несколько контейнеров.

public static void DeleteContainer(
 IObjectStorageProvider provider,
 string containerName)
{
 while (true)
 {
 // The only reliable way to determine if a container is empty is
 // to list its objects
 ContainerObject[] objects = provider.ListObjects(containerName);
 if (!objects.Any())
 break;

 // the iterations of this loop should be executed concurrently.
 // depending on connection speed, expect to use 25 to upwards of 300
 // concurrent connections for best performance.
 foreach (ContainerObject obj in objects)
 {
 try
 {
 provider.DeleteObject(containerName, obj.Name);
 }
 catch (ItemNotFoundException)
 {
 // a 404 can happen if the object was deleted on a previous iteration,
 // but the internal database did not fully synchronize prior to calling
 // List Objects again.
 }
 }
 }

 provider.DeleteContainer(containerName);
}

licensed under cc by-sa 3.0 with attribution.