【问题标题】:Copy Azure Blob With Snapshots使用快照复制 Azure Blob
【发布时间】:2016-02-13 04:06:10
【问题描述】:

我正在尝试备份一些 blob 存储以防止意外删除容器,我可以使用 PowerShell 和 start-CopyAzurBlog 或从命令行使用 AZCopy 复制 blob,但是这些 blob 有一个编号快照(用作版本控制过程的一部分),并且每当我复制时,它都不会拍摄快照。

我知道您可以将 /snapshot 命令与 AZCopy 一起使用,但这会为每个快照创建一个全新的 blob,我需要它们成为单个 blob 的一部分。 反正有没有原封不动地复制这些?理想情况下,这将在 PowerShell 中,因此我可以使用 Azure 自动化,但如果需要,我很乐意在 C# 中做一些事情。

【问题讨论】:

    标签: powershell azure azure-storage azure-blob-storage


    【解决方案1】:

    这是符合卢兆兴逻辑的代码。该方法是首先列出源 blob 的快照,从快照在目标中创建 blob 并拍摄该 blob 的快照。最后,您将基础 blob 复制到目标 blob。

        static void CopyBlobAndSnapshots()
        {
            var sourceAccountName = "<source-account-name>";
            var sourceAccountKey = "<source-account-key>";
            var sourceContainerName = "<source-container-name>";
            var targetAccountName = "<target-account-name>";
            var targetAccountKey = "<target-account-key>";
            var targetContainerName = "<target-container-name>";
            var blobName = "<source-blob-name>";
            var sourceAccount = new CloudStorageAccount(new StorageCredentials(sourceAccountName, sourceAccountKey), true);
            var targetAccount = new CloudStorageAccount(new StorageCredentials(targetAccountName, targetAccountKey), true);
            var sourceBlobClient = sourceAccount.CreateCloudBlobClient();
            var sourceContainer = sourceBlobClient.GetContainerReference(sourceContainerName);
            var sourceBlob = sourceContainer.GetBlockBlobReference(blobName);
            var targetBlobClient = targetAccount.CreateCloudBlobClient();
            var targetContainer = targetBlobClient.GetContainerReference(targetContainerName);
            targetContainer.CreateIfNotExists();
            //Create a SAS Token on source blob with read permissions that is valid for 2 weeks.
            var sasToken = sourceBlob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
                {
                    Permissions = SharedAccessBlobPermissions.Read,
                    SharedAccessExpiryTime = new DateTimeOffset(DateTime.UtcNow.AddDays(14))
                });
            //List blob snapshots first
            var baseBlobAndSnapshots = sourceContainer.ListBlobs(blobName, true, BlobListingDetails.Snapshots).ToList();
            //Since the list contains both base blob and snapshots, we should remove the base blob from this list.
            var blobSnapshots = baseBlobAndSnapshots.Where(b => ((CloudBlockBlob)b).SnapshotTime != null).ToList();
            //Now we should arrange them in reverse chronological order
            blobSnapshots.Reverse();
            CloudBlockBlob targetBlob = null;
            string sourceBlobUrl = string.Empty;
            foreach (var blob in blobSnapshots)
            {
                var blockBlob = (CloudBlockBlob) blob;
                Console.WriteLine("Copying blob snapshot. Snapshot date/time = " + blockBlob.SnapshotTime);
                sourceBlobUrl = string.Format("{0}&{1}", blockBlob.SnapshotQualifiedUri, sasToken.Substring(1));
                targetBlob = targetContainer.GetBlockBlobReference(blobName);
                targetBlob.StartCopy(new Uri(sourceBlobUrl));
                //Check the status;
                targetBlob.FetchAttributes();
                do
                {
                    var copyState = targetBlob.CopyState;
                    if (copyState.Status == CopyStatus.Pending)
                    {
                        Thread.Sleep(1000);//Copy not completed. Wait for it to complete.
                        targetBlob.FetchAttributes();
                    }
                    else
                    {
                        break;
                    }
                } 
                while (true);
                Console.WriteLine("Copying blob snapshot complete. Snapshot date/time = " + blockBlob.SnapshotTime);
                Console.WriteLine("----------------------------");
                //Now take the blob snapshot
                Console.WriteLine("Taking blob snapshot....");
                targetBlob.Snapshot();
                Console.WriteLine("Blob snapshot taken....");
                Console.WriteLine("----------------------------");
            }
            Console.WriteLine("Copying base blob.");
            sourceBlobUrl = string.Format("{0}{1}", sourceBlob.Uri, sasToken);
            targetBlob = targetContainer.GetBlockBlobReference(blobName);
            targetBlob.StartCopy(new Uri(sourceBlobUrl));
            //Check the status;
            targetBlob.FetchAttributes();
            do
            {
                var copyState = targetBlob.CopyState;
                if (copyState.Status == CopyStatus.Pending)
                {
                    Thread.Sleep(1000);//Copy not completed. Wait for it to complete.
                    targetBlob.FetchAttributes();
                }
                else
                {
                    break;
                }
            } 
            while (true);
            Console.WriteLine("Blob with snapshot copy completed!");
        }
    

    【讨论】:

      【解决方案2】:

      我必须指出,您所要求的功能很难实现。

      Snapshot Blob API 仅支持为当前 blob 数据创建快照。因此,为了备份快照,我们需要在目的地创建与第一个快照相同数据的 blob,然后创建快照;并用与第二个快照相同的数据覆盖目标 blob,然后创建快照; ... ;继续这样做,直到在目标中创建所有快照,最后用与当前源 blob 相同的数据覆盖目标 blob。

      由于源 blob 的容量实际上并未按所有快照和当前 blob 的总和计费,如果您想在备份后保存目标的价格,则必须在两个快照之间或最后一个快照之间进行区分& 当前的 blob,并且只在每一步覆盖不同的块/页面,这可能会引入更多的复杂性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-25
        • 2016-08-10
        • 1970-01-01
        • 1970-01-01
        • 2021-01-10
        • 1970-01-01
        • 1970-01-01
        • 2018-02-03
        相关资源
        最近更新 更多