我使用的是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失败:)。最大的问题是我正在丢失数据。
答案 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,从而认为他们都是领导者。