将存储数据从一个 Azure 帐户复制到另一个

Posted

技术标签:

【中文标题】将存储数据从一个 Azure 帐户复制到另一个【英文标题】:Copying storage data from one Azure account to another 【发布时间】:2012-01-24 19:29:07 【问题描述】:

我想将一个非常大的存储容器从一个 Azure 存储帐户复制到另一个帐户(恰好也在另一个订阅中)。

我想对以下选项发表意见:

    编写一个工具,使用 CloudBlob 的 DownloadToStream() 和 UploadFromStream() 连接两个存储帐户并一次复制一个 Blob。这似乎是最糟糕的选择,因为它会在传输数据时产生成本,而且速度很慢,因为数据必须下降到运行该工具的机器上,然后重新上传回 Azure。

    李>

    写一个工人角色来做同样的事情 - 理论上这应该更快并且不会产生任何成本。然而,这是更多的工作。

    将工具上传到正在运行的实例,绕过辅助角色部署,并祈祷工具在实例被回收/重置之前完成。

    使用现有工具 - 没有发现任何有趣的东西。

对方法有什么建议吗?

更新:我刚刚发现终于为 2012 年 7 月 7 日或之后创建的所有存储帐户引入了此功能(目前仅限 REST API):

http://msdn.microsoft.com/en-us/library/windowsazure/dd894037.aspx

【问题讨论】:

试试Azure Storage Synctool。 Azure Storage Synctool 有点原始 - 仅支持 Storage-to-local(这意味着我需要分两步完成,首先下载我的整个容器,然后重新上传它,这没什么大不了的),而且大多数情况下,它不会恢复-这可能有点问题。我们最终构建的自主解决方案(非常简单)支持恢复、存储到存储并在同一帐户上使用 CopyFromBlob。 【参考方案1】:

由于没有直接的方法可以将数据从一个存储帐户迁移到另一个,因此您需要按照您的想法进行操作。如果这是在同一个数据中心内,选项 #2 是最好的选择,而且速度最快(特别是如果您使用 XL 实例,可以为您提供更多的网络带宽)。

就复杂性而言,以工作者角色创建此代码并不比使用本地应用程序更难。只需从您的辅助角色的 Run() 方法运行此代码即可。

为了使事情变得更加健壮,您可以列出容器中的 blob,然后将特定的文件移动请求消息放入 Azure 队列(并通过在每条消息中放置多个对象名称进行优化)。然后使用工作者角色线程从队列中读取并处理对象。即使您的角色被回收,最坏的情况是您会重新处理一条消息。为了提高性能,您可以扩展到多个工作角色实例。传输完成后,您只需拆除部署即可。

更新 - 2012 年 6 月 12 日,更新了 Windows Azure 存储 API,现在允许跨帐户 blob 复制。详情请见this blog post。

【讨论】:

要注意的一件有趣的事情是,如果容器在同一个存储帐户上(不幸的是,我不是这种情况),那么有一种方法可以在不经过客户端的情况下复制 blob - 不是确定是哪个 API 执行此操作,但在使用 Azure 存储资源管理器进行复制时运行 Fiddler 会显示 x-ms-copy-source 标头。 好的,它叫做“CopyFromBlob”。可以检查源帐户是否与目标帐户匹配并使用该方法,否则使用 DownloadToStream/UploadToStream 组合。【参考方案2】:

将您的工具编写为简单的 .NET 命令行或 Win Forms 应用程序。

在启用 RDP 的情况下创建和部署一个虚拟的 we/worker 角色

通过 RDP 登录机器

通过 RDP 连接复制您的工具

在远程机器上运行该工具

删除已部署的角色。

和你一样,我不知道有任何现成的工具支持功能之间的复制。 您可能想考虑将 Cloud Storage Studio 安装到角色中,然后转储到磁盘然后重新上传。 http://cerebrata.com/Products/CloudStorageStudiov2/Details.aspx?t1=0&t2=7

【讨论】:

不确定您为什么要提出 RDP。除了需要手动操作之外,您还需要使用您的部署部署您的 WinForms 应用程序。运行简单任务的简单工作者角色更简单,并且可以扩展到多个实例以获得更快的性能。 原始发帖人特别指出,他发现写一个“工具”比写一个工人角色更快。同意我通常会写一个工人来做这件事,但在这种情况下,我试图提供一个注意这个约束的答案。您不需要部署 WInForms 应用程序;从字面上看,您只需将其拖过 RDP 链接,就像您连接并使用本地服务器一样。 实际上,我最终做了很多事情 - 将我的 WinForm 复制粘贴到一个正在运行的 Web 角色中,然后从那里运行它。即使它在那里运行,它仍然不是闪电般快:复制大约 400,000 个项目(主要是中型 jpeg)需要大约 22 小时 - 价值 46.5GB 的数据 - 我本来预计它会快得多(不再超过 5 小时)。【参考方案3】:

这里有一些利用 .NET SDK for Azure 的代码,可在 http://www.windowsazure.com/en-us/develop/net 获得

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure.StorageClient;
using System.IO;
using System.Net;

namespace benjguinAzureStorageTool

    class Program
    
        private static Context context = new Context();

        static void Main(string[] args)
        
            try
            
                string usage = string.Format("Possible Usages:\n"
                + "benjguinAzureStorageTool CopyContainer account1SourceContainer account2SourceContainer account1Name account1Key account2Name account2Key\n"
                );


                if (args.Length < 1)
                    throw new ApplicationException(usage);

                int p = 1;

                switch (args[0])
                
                    case "CopyContainer":
                        if (args.Length != 7) throw new ApplicationException(usage);
                        context.Storage1Container = args[p++];
                        context.Storage2Container = args[p++];
                        context.Storage1Name = args[p++];
                        context.Storage1Key = args[p++];
                        context.Storage2Name = args[p++];
                        context.Storage2Key = args[p++];

                        CopyContainer();
                        break;


                    default:
                        throw new ApplicationException(usage);
                

                Console.BackgroundColor = ConsoleColor.Black;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("OK");
                Console.ResetColor();
            
            catch (Exception ex)
            
                Console.WriteLine();
                Console.BackgroundColor = ConsoleColor.Black;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("Exception: 0", ex.Message);
                Console.ResetColor();
                Console.WriteLine("Details: 0", ex);
            
        


        private static void CopyContainer()
        
            CloudBlobContainer container1Reference = context.CloudBlobClient1.GetContainerReference(context.Storage1Container);
            CloudBlobContainer container2Reference = context.CloudBlobClient2.GetContainerReference(context.Storage2Container);
            if (container2Reference.CreateIfNotExist())
            
                Console.WriteLine("Created destination container 0. Permissions will also be copied.", context.Storage2Container);
                container2Reference.SetPermissions(container1Reference.GetPermissions());
            
            else
            
                Console.WriteLine("destination container 0 already exists. Permissions won't be changed.", context.Storage2Container);
            


            foreach (var b in container1Reference.ListBlobs(
                new BlobRequestOptions(context.DefaultBlobRequestOptions)
                 UseFlatBlobListing = true, BlobListingDetails = BlobListingDetails.All ))
            
                var sourceBlobReference = context.CloudBlobClient1.GetBlobReference(b.Uri.AbsoluteUri);
                var targetBlobReference = container2Reference.GetBlobReference(sourceBlobReference.Name);

                Console.WriteLine("Copying 0\n to\n1",
                    sourceBlobReference.Uri.AbsoluteUri,
                    targetBlobReference.Uri.AbsoluteUri);

                using (Stream targetStream = targetBlobReference.OpenWrite(context.DefaultBlobRequestOptions))
                
                    sourceBlobReference.DownloadToStream(targetStream, context.DefaultBlobRequestOptions);
                
            
        
    

【讨论】:

谢谢!我已经编写了解决方案,但是看到一些代码共享出来总是很高兴。另外,我正在创建一个 MemoryStream - 在目标 blob 上执行 OpenWrite() 更简洁(也更高效)。【参考方案4】:

可以使用“Azure 存储资源管理器”(免费)或其他类似工具。这些工具提供了一种下载和上传内容的方法。您将需要手动创建容器和表格 - 当然这会产生转移成本 - 但如果您时间紧迫且内容大小合理,那么这是一个可行的选择。

【讨论】:

如最初所述,我必须复制的容器非常大 - Azure 存储资源管理器在这种情况下表现不佳。我最终编写了一个自定义工具 - 它非常简单 - 我从 Azure Web 角色运行它以避免转移成本。【参考方案5】:

我不得不做一些类似的事情,将 600 GB 的内容从本地文件系统移动到 Azure 存储。经过几次代码迭代后,我最终采用了“Azure 存储资源管理器”并将其扩展为选择文件夹而不仅仅是文件的能力,然后让它递归地钻入多个选定的文件夹,加载源/目标副本列表将项目语句放入 Azure 队列。然后在“Azure 存储资源管理器”的上传部分,在队列部分从队列中拉取并执行复制操作。

然后我启动了大约 10 个“Azure 存储资源管理器”工具实例,每个实例都从队列中拉出并执行复制操作。我能够在短短 2 天内移动 600 GB 的物品。添加了智能以利用文件上修改后的时间戳,并让它跳过已经从队列中复制的文件,如果同步则不添加到队列中。现在,我可以在一两个小时内跨整个内容库运行“更新”或同步。

【讨论】:

【参考方案6】:

我是 Microsoft 技术布道者,我开发了一个示例和免费工具(不支持/不保证)来帮助解决这些情况。

二进制文件和源代码可在此处获得:https://blobtransferutility.codeplex.com/

Blob 传输实用程序是一个 GUI 工具,用于向/从 Windows Azure Blob 存储上传和下载数千个小/大文件。

特点:

创建要上传/下载的批次 设置内容类型 并行传输文件 将大文件拆分为并行传输的较小部分

第一个和第三个功能是您问题的答案。

您可以从示例代码中了解我是如何做到的,或者您可以简单地运行该工具并做您需要做的事情。

【讨论】:

【参考方案7】:

您还可以使用 Azure SDK 中的 AzCopy。

只需单击 Windows Azure SDK 的下载按钮并从列表中选择 WindowsAzureStorageTools.msi 即可下载 AzCopy。

安装后,你会在这里找到AzCopy.exe%PROGRAMFILES(X86)%\Microsoft SDKs\Windows Azure\AzCopy

您可以在此博客文章中获取有关使用 AzCopy 的更多信息:AzCopy – Using Cross Account Copy Blob

同样,您可以远程桌面进入一个实例并使用此实用程序进行传输。

更新:

您还可以使用 Microsoft Azure 存储资源管理器 在存储帐户之间复制 blob 数据。参考link

【讨论】:

【参考方案8】:

使用 AzCopy 非常简单。从https://azure.microsoft.com/en-us/documentation/articles/storage-use-azcopy/下载最新版本 在 azcopy 类型中: 在存储帐户中复制 Blob:

AzCopy /Source:https://myaccount.blob.core.windows.net/mycontainer1 /Dest:https://myaccount.blob.core.windows.net/mycontainer2 /SourceKey:key /DestKey:key /Pattern:abc.txt

跨存储帐户复制 blob:

AzCopy /Source:https://sourceaccount.blob.core.windows.net/mycontainer1 /Dest:https://destaccount.blob.core.windows.net/mycontainer2 /SourceKey:key1 /DestKey:key2 /Pattern:abc.txt

从次要区域复制 blob

如果您的存储帐户启用了读取访问异地冗余存储,那么您可以从次要区域复制数据。

将 blob 从辅助帐户复制到主帐户:

AzCopy /Source:https://myaccount1-secondary.blob.core.windows.net/mynewcontainer1 /Dest:https://myaccount2.blob.core.windows.net/mynewcontainer2 /SourceKey:key1 /DestKey:key2 /Pattern:abc.txt

【讨论】:

【参考方案9】:

试试CloudBerry Explorer。它在订阅内和订阅之间复制 blob。

要在订阅之间进行复制,请将存储帐户容器的访问权限从 Private 编辑为 Public Blob

复制过程需要几个小时才能完成。如果您选择重新启动计算机,该过程将继续。通过检查时间戳刷新 Azure 管理 UI 中的目标存储帐户容器来检查状态,直到复制过程完成,值才会更新。

【讨论】:

【参考方案10】:

我推荐使用azcopy,你可以复制所有的存储帐户、一个容器、一个目录或单个blob。以下是克隆所有存储帐户的示例:

azcopy copy 'https://SOURCE_ACCOUNT.blob.core.windows.netSOURCE_SAS_TOKEN' 'https://DESTINATION_ACCOUNT.blob.core.windows.netDESTINATION_SAS_TOKEN' --recursive

您可以从 Azure 门户获取 SAS 令牌。导航到存储帐户概述(源和目标),然后在 sidenav 中单击“共享访问信号”并生成您自己的。

更多例子here

【讨论】:

以上是关于将存储数据从一个 Azure 帐户复制到另一个的主要内容,如果未能解决你的问题,请参考以下文章

Azure Blob 存储:防止 Blob 复制到另一个存储帐户的最佳方法?

我们如何将 azure 存储帐户表复制到另一个存储帐户?

如何将 Azure 存储帐户内容(表、队列、blob)复制到其他存储帐户

将 VHD 从 azure 磁盘复制到 azure 存储帐户

将 Parquet 文件从 Azure 数据湖存储帐户复制到 Synapse 数据仓库表失败

使用 powershell 在 Azure 中不同订阅的存储容器之间复制 blob