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

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

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 обрабатываются в указанном порядке, поэтому объекты в контейнере должны быть перечислены первыми, чтобы очистить контейнер.

В одном запросе может быть удалено до 10000 объектов. Сервер ответит 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);
}
Другие вопросы по тегам