3

我正在使用 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(通常由领导者创建)=> 每台机器都在尝试创建它并将其元数据写入它(每个人都想成为领导者)。理论上,如果有 2 台机器正在执行此代码。机器 A 调用_pageBlob.Create(),没有错误,写入元数据认为它是领导者。机器B调用_pageBlob.Create(),没有错误,机器A的元数据(+可能更多的数据)被机器B重写。我希望机器B失败:)。最大的问题是我丢失了数据。

4

4 回答 4

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(),则第二次调用失败。我到底想要什么。谢谢大家的帮助。

于 2014-03-17T16:12:53.347 回答
0

In this scenario, you'd better implement a queue to act as a flag. You'll create and send a message to a queue as a request to create your page blob. So, only one machine will dequeue the message and then call your pageBlob create method.

于 2014-03-12T17:01:59.767 回答
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,从而认为它们都是领导者)。

于 2014-03-13T11:28:29.427 回答
0

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

CloudPageBlob _pageBlob = .....
try
{
    acquireBlobLease();
    try
    {
        _pageBlob.FetchAttributes();             
    }
    catch
    {
        //container does not exist
        _pageBlob.Create(AllocatedBlobSize);
    }
}
catch
{
}
于 2014-03-12T17:27:56.103 回答