Удалите огромное количество файлов в 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);
}