【问题标题】:Moving Millions of items from one Storage Account to Another将数百万个项目从一个存储帐户转移到另一个
【发布时间】:2013-03-02 21:39:53
【问题描述】:

作为利用 Azure VM 支持的大规模迁移的一部分,我需要将大约 420 万张图像从美国中北部迁移到美国西部(对于那些不知道的人,美国中北部不支持它们)。图像都在一个容器中,分为大约 119,000 个目录。

我正在使用 Copy Blob API 中的以下内容:

public static void CopyBlobDirectory(
        CloudBlobDirectory srcDirectory,
        CloudBlobContainer destContainer)
{
    // get the SAS token to use for all blobs
    string blobToken = srcDirectory.Container.GetSharedAccessSignature(
        new SharedAccessBlobPolicy
        {
            Permissions = SharedAccessBlobPermissions.Read |
                            SharedAccessBlobPermissions.Write,
            SharedAccessExpiryTime = DateTime.UtcNow + TimeSpan.FromDays(14)
        });

    var srcBlobList = srcDirectory.ListBlobs(
        useFlatBlobListing: true,
        blobListingDetails: BlobListingDetails.None).ToList();

    foreach (var src in srcBlobList)
    {
        var srcBlob = src as ICloudBlob;

        // Create appropriate destination blob type to match the source blob
        ICloudBlob destBlob;
        if (srcBlob.Properties.BlobType == BlobType.BlockBlob)
            destBlob = destContainer.GetBlockBlobReference(srcBlob.Name);
        else
            destBlob = destContainer.GetPageBlobReference(srcBlob.Name);

        // copy using src blob as SAS
        destBlob.BeginStartCopyFromBlob(new Uri(srcBlob.Uri.AbsoluteUri + blobToken), null, null);          
    }
}

问题是,它太慢了。哇哇太慢了。按照发出命令复制所有这些东西的速度,这将需要大约四天的时间。我不太确定瓶颈是什么(连接限制客户端、Azure 端的速率限制、多线程等)。

所以,我想知道我的选择是什么。有什么办法可以加快速度,还是我只是坚持需要四天才能完成的工作?

编辑:我如何分发作品以复制所有内容

//set up tracing
InitTracer();

//grab a set of photos to benchmark this
var photos = PhotoHelper.GetAllPhotos().Take(500).ToList();

//account to copy from
var from = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
    "oldAccount",
    "oldAccountKey");
var fromAcct = new CloudStorageAccount(from, true);
var fromClient = fromAcct.CreateCloudBlobClient();
var fromContainer = fromClient.GetContainerReference("userphotos");

//account to copy to
var to = new Microsoft.WindowsAzure.Storage.Auth.StorageCredentials(
    "newAccount",
    "newAccountKey");
var toAcct = new CloudStorageAccount(to, true);
var toClient = toAcct.CreateCloudBlobClient();

Trace.WriteLine("Starting Copy: " + DateTime.UtcNow.ToString());

//enumerate sub directories, then move them to blob storage
//note: it doesn't care how high I set the Parallelism to,
//console output indicates it won't run more than five or so at a time
var plo = new ParallelOptions { MaxDegreeOfParallelism = 10 };
Parallel.ForEach(photos, plo, (info) =>
{
    CloudBlobDirectory fromDir = fromContainer.GetDirectoryReference(info.BuildingId.ToString());

    var toContainer = toClient.GetContainerReference(info.Id.ToString());
    toContainer.CreateIfNotExists();

    Trace.WriteLine(info.BuildingId + ": Starting copy, " + info.Photos.Length + " photos...");

    BlobHelper.CopyBlobDirectory(fromDir, toContainer, info);
    //this monitors the container, so I can restart any failed
    //copies if something goes wrong
    BlobHelper.MonitorCopy(toContainer);
});

Trace.WriteLine("Done: " + DateTime.UtcNow.ToString());

【问题讨论】:

  • 您是否使用大量线程来执行此操作?大部分时间都在抄袭。我认为你可以极大地并行化它。也许在 azure 上有一堆工人角色。
  • 我也有同样的想法;最初我是同步运行的。经过一些测试,这需要将近两周的时间,所以我重写了它以使用 BeginStartCopyFromBlob(),并将对 CopyBlobDirectory() 的调用包装在 Parallel.ForEach 中。但是,Parallel 框架不允许我一次运行超过 5 个左右的作业(即使我设置了更高的度数);我不确定如何强制它运行更多。
  • 您能否像这样生成大量线程:stackoverflow.com/questions/5041153/…,例如每个工作实例 1000 个,然后启动几十个工作角色?
  • 我编辑了这篇文章,以说明我是如何管理所有复制工作的。
  • 您会说开始每个副本大约需要 500 毫秒吗?

标签: c# azure parallel-processing azure-blob-storage parallel.foreach


【解决方案1】:

异步 ​​blob 复制操作在同一个数据中心内将非常快(最近我在大约 1-2 秒内将 30GB vhd 复制到另一个 blob)。跨数据中心,操作排队并发生在没有 SLA 的备用容量中(请参阅this article,其中特别指出了这一点)

从这个角度来看:我跨数据中心复制了相同的 30GB VHD,花了大约 1 小时。

我不知道您的图像大小,但假设平均图像大小为 500K,您会看到大约 2,000 GB。在我的示例中,我在大约一个小时内看到了 30GB 的吞吐量。推断,这将估计您的 2000 GB 数据在大约 (2000/30) = 60 小时内。同样,没有 SLA。只是一个最好的猜测。

其他人建议禁用 Nagle 的算法。这应该有助于更快地推出 400 万条复制命令并让它们更快地排队。我认为它不会对复制时间产生任何影响。

【讨论】:

    【解决方案2】:

    这有点远,但我在表存储方面遇到了类似的问题,即小请求(我认为BeginStartCopyFromBlob 应该是)开始运行非常缓慢。这是Nagle's Algorithmdelayed TCP acks 的问题,这两个优化网络流量。请参阅MSDNthis guy 了解更多详情。

    结果 - 关闭 Nagle 的算法 - 在执行任何 Azure 存储操作之前调用以下

    ServicePointManager.UseNagleAlgorithm = false;
    

    或者只是 blob:

    var storageAccount = CloudStorageAccount.Parse(connectionString);
    ServicePoint blobServicePoint = ServicePointManager.FindServicePoint(account.BlobEndpoint);
    blobServicePoint.UseNagleAlgorithm = false;
    

    很高兴知道这是否是您的问题!

    【讨论】:

    • 试试这个;到目前为止,似乎已经给它注射了肾上腺素 :)。
    • 请记住,复制操作不会在存储和计算实例之间传输数据;这是存储到存储的异步复制。您将看到的唯一改进(在这种情况下关闭 Nagle)是发送/完成每个单独复制命令的速度。这应该可以让您更快地发送命令。
    • 是的,没关系。最初的问题是弄清楚为什么发送请求需要这么长时间。您是否知道 Azure 实际执行 blob 副本需要多长时间?比如说,一组 1,000 个 Blob?
    • 跨数据中心的异步 blob 复制没有 SLA,所以我真的不能告诉你多长时间。但是...我刚刚发布了一个答案,根据我在自己的 blob 复制工作中进行的一些性能测量,为您提供了一些简单的猜测。
    • 所以这似乎让您在合理的时间范围内将这些移动排队(即使复制实际上需要更长的时间)?很高兴知道 - 这是 Azure 存储的一个奇怪的小怪癖,让我摸不着头脑......
    猜你喜欢
    • 2017-05-22
    • 2016-09-18
    • 1970-01-01
    • 2011-09-01
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-18
    相关资源
    最近更新 更多