Azure CloudPageBlob Create - 如何实现CreateIfNotExist

时间:2014-03-12 16:48:35

标签: azure azure-storage-blobs blobstorage

我使用的是Azure SDK 2.2版。我遇到了问题,在我的代码中可能有多台机器调用此代码

CloudPageBlob _pageBlob = .....
try
{
    _pageBlob.FetchAttributes();             
}
catch
{
    //container does not exist
    _pageBlob.Create(AllocatedBlobSize);
}

我已对其进行了测试,我的结论是多次调用_pageBlob.Create(AllocatedBlobSize); 清除之前的数据。如何确保只有一台机器获胜并创建CloudPageBlob? (我希望其他人失败)我期待多个Create调用会导致异常,但事实并非如此:(。

编辑:在我们的架构中,有一位领导者和X粉丝。我正在使用CloudPageBlob + ETAG来选举新的领导者(只有一台机器能够将它的元数据写入CloudPageBlob =新的领导者)。但是有一种极端的情况,当这个云页面blob可能被破坏+领导者死亡(或者我们正在开始并且还没有领导者)。在这种情况下,我需要创建新的CloudPageBlob(normaly leader创建它)=>每台机器都试图创建它并将它的元数据写入其中(每个人都希望成为领导者)。理论上,如果2台机器正在执行此代码。机器A调用_pageBlob.Create(),没有错误,写入元数据认为它是领导者。机器B调用_pageBlob.Create(),没有错误,机器A的元数据(+可能更多的数据)被机器B重写。我希望机器B失败:)。最大的问题是我正在丢失数据。

4 个答案:

答案 0 :(得分:1)

我发现的解决方案是使用AccessCondition.IfNotModifiedSince。

var timeOffset = new DateTimeOffset(new DateTime(1, 1, 1), TimeSpan.FromMilliseconds(0));
var cond = AccessCondition.GenerateIfNotModifiedSinceCondition(timeOffset);
var options = new BlobRequestOptions ();
pageBlob.Create(AllocatedBlobSize, cond, options);

现在如果我以相同的条件第二次调用CloudPageBlob.Create(),则第二次调用失败。我究竟想要什么。谢谢大家的帮助。

答案 1 :(得分:0)

在这种情况下,您最好将队列实现为标志。您将创建消息并将其作为创建页面blob的请求发送到队列。因此,只有一台机器会将消息出列,然后调用pageBlob创建方法。

答案 2 :(得分:0)

另一种方法是使用 blob leasing 。您将拥有一个块blob并让所有实例尝试获取该Blob上的租约。只有一个实例能够成功。成功的实例将调用代码来创建blob。根据您在应用程序生命周期中何时调用该操作,您可能仍然必须使用上面的代码,以便在blob已经存在的情况下,您不会重新创建它。

CloudPageBlob _pageBlob = .....
try
{
    acquireBlobLease();
    try
    {
        _pageBlob.FetchAttributes();             
    }
    catch
    {
        //container does not exist
        _pageBlob.Create(AllocatedBlobSize);
    }
}
catch
{
}

答案 3 :(得分:0)

我称之为“交通警察”模式,但我也听说它称为“领导选举”模式(http://msdn.microsoft.com/en-us/library/dn568104.aspx)。最好的方法是使用blob租约。我实际上创建了一些示例c#代码,您可以使用这些代码来帮助实现此目的:http://brentdacodemonkey.wordpress.com/2012/07/27/the-traffic-cop-pattern/

只要有一个进程在当前领导者“死亡”时插入新队列消息,队列就能正常工作。您还已经指出了元数据方法的问题。 blob租约通过确保只有一个实例获得租约来解决这个问题,如果该实例死亡,租约将被释放并且可以选出新的领导者。

至于您的原始示例,我建议您将blob创建为部署甚至预部署的一部分。这消除了将blob创建作为角色实例的一部分进行管理的需要(减少对存储的操作)。如果你对这条路线感到不舒服,那么稍微翻转一下你的代码并尝试进行创建,如果已经存在则进行异常陷阱,然后继续处理并尝试进行更新(无论如何都需要租用防止两个实例同时使用他们的元数据更新blob,从而认为他们都是领导者。