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

将存储数据从一个Azure帐户复制到另一个Azure帐户,azure,azure-storage,azure-storage-blobs,replication,Azure,Azure Storage,Azure Storage Blobs,Replication,我想将一个非常大的存储容器从一个Azure存储帐户复制到另一个Azure存储帐户(该帐户恰好位于另一个订阅中) 我想就以下选择发表意见: 编写一个工具,使用CloudBlob的DownloadToStream()和UploadFromStream()连接到两个存储帐户并一次复制一个Blob。这似乎是最糟糕的选择,因为它在传输数据时会产生成本,而且速度相当慢,因为数据将必须到达运行该工具的机器,然后重新上传回Azure 写一个工人角色来做同样的事情——理论上这应该更快,而且不会产生任何成本。然而,

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

我想就以下选择发表意见:

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

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

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

  • 使用现有工具-未发现任何有趣的内容

  • 对这个方法有什么建议吗

    更新:我刚刚发现,对于2012年7月7日或更高日期创建的所有存储帐户,此功能终于被引入(仅限目前使用REST API):


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

    就复杂性而言,在工作者角色中创建此代码并不比在本地应用程序中创建此代码更困难。只需从工作者角色的run()方法运行此代码

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


    更新-2012年6月12日,更新了Windows Azure存储API,现在允许跨帐户blob复制。有关所有详细信息,请参阅。

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

    创建并部署启用RDP的虚拟we/worker角色

    通过RDP登录到机器

    通过RDP连接复制工具

    在远程机器上运行该工具

    删除已部署的角色

    像你一样,我不知道有任何现成的工具支持复制功能。
    您可能会考虑仅将云存储演播室安装到角色中,然后将其卸载到磁盘,然后重新上传。p> 以下是一些利用.NET SDK for Azure的代码,可在

    使用系统;
    使用System.Collections.Generic;
    使用System.Linq;
    使用系统文本;
    使用Microsoft.WindowsAzure.StorageClient;
    使用System.IO;
    Net系统;
    名称空间benjguinAzureStorageTool
    {
    班级计划
    {
    私有静态上下文=新上下文();
    静态void Main(字符串[]参数)
    {
    尝试
    {
    字符串用法=string.Format(“可能的用法:\n”
    +“benjguinAzureStorageTool CopyContainer account1SourceContainer account2SourceContainer account1Name account1Key account2Name account2Key\n”
    );
    如果(参数长度<1)
    抛出新的ApplicationException(用法);
    int p=1;
    开关(参数[0])
    {
    案例“CopyContainer”:
    如果(args.Length!=7)抛出新的ApplicationException(用法);
    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();
    打破
    违约:
    抛出新的ApplicationException(用法);
    }
    Console.BackgroundColor=ConsoleColor.Black;
    Console.ForegroundColor=ConsoleColor.Yellow;
    控制台。写入线(“OK”);
    Console.ResetColor();
    }
    捕获(例外情况除外)
    {
    Console.WriteLine();
    Console.BackgroundColor=ConsoleColor.Black;
    Console.ForegroundColor=ConsoleColor.Yellow;
    WriteLine(“异常:{0}”,例如Message);
    Console.ResetColor();
    WriteLine(“详细信息:{0}”,例如);
    }
    }
    私有静态void CopyContainer()
    {
    CloudBlobContainer容器1引用=context.CloudBlobClient 1.GetContainerReference(context.Storage1Container);
    CloudBlobContainer container2Reference=context.CloudBlobClient 2.GetContainerReference(context.Storage2Container);
    if(container2Reference.CreateIfNotExist())
    {
    WriteLine(“已创建的目标容器{0}。权限也将被复制。”,context.Storage2Container);
    container2Reference.SetPermissions(container1Reference.GetPermissions());
    }
    其他的
    {
    WriteLine(“目标容器{0}已存在。权限不会更改。”,context.Storage2Container);
    }
    foreach(container1Reference.ListBlobs中的变量b(
    新BlobRequestOptions(context.DefaultBl
    
    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\n{1}",
                        sourceBlobReference.Uri.AbsoluteUri,
                        targetBlobReference.Uri.AbsoluteUri);
    
                    using (Stream targetStream = targetBlobReference.OpenWrite(context.DefaultBlobRequestOptions))
                    {
                        sourceBlobReference.DownloadToStream(targetStream, context.DefaultBlobRequestOptions);
                    }
                }
            }
        }
    }
    
    AzCopy /Source:https://myaccount.blob.core.windows.net/mycontainer1 /Dest:https://myaccount.blob.core.windows.net/mycontainer2 /SourceKey:key /DestKey:key /Pattern:abc.txt
    
    AzCopy /Source:https://sourceaccount.blob.core.windows.net/mycontainer1 /Dest:https://destaccount.blob.core.windows.net/mycontainer2 /SourceKey:key1 /DestKey:key2 /Pattern:abc.txt
    
    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
    
    azcopy copy 'https://{SOURCE_ACCOUNT}.blob.core.windows.net{SOURCE_SAS_TOKEN}' 'https://{DESTINATION_ACCOUNT}.blob.core.windows.net{DESTINATION_SAS_TOKEN}' --recursive