2014-03-12 1 views
3

Я использую Azure SDK версии 2.2. Я имею проблему, что в моем коде потенциально несколько машин называют этому кодAzure CloudPageBlob Create - как реализовать CreateIfNotExist

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

Я испытал это, и мой вывод, что несколько вызовов из _pageBlob.Create(AllocatedBlobSize);очищают предыдущих данные. Как убедиться, что побеждает только одна машина и создает CloudPageBlob? (Я хочу, чтобы другие терпели неудачу) Я ожидал, что несколько вызовов Create приведут к исключению, но это не то, что происходит :(

EDIT: В нашей архитектуре есть один лидер и X-последователи. Я использую CloudPageBlob + ETAG, чтобы избрать нового лидера (только одна машина сможет записать метаданные в CloudPageBlob = новый лидер). Но есть крайний случай, когда этот куб облачной страницы может быть поврежден + лидер умирает (или мы начинаем, и нет лидера пока). В этом случае мне нужно создать новый CloudPageBlob (нормальный лидер создает его) => каждая машина пытается его создать и писать ему метаданные (все хотят быть лидером). Теоретически, если 2 машины выполнялись этот код. Машина A вызывает _pageBlob.Create(), без ошибок, пишет метаданные, думает, что это лидер. Machine B call _pageBlob.Create(), без ошибок, метаданные ma chine A (+ потенциально больше данных) переписаны машиной B. Я хочу, чтобы машина B не сработала :). Самая большая проблема заключается в том, что я теряю данные.

+0

Не могли бы вы описать сценарий, который вы пытаетесь решить? Возможно, есть лучший подход. :) – BrentDaCodeMonkey

+0

описано, надеюсь, что это поможет. На самом деле самой большой проблемой является потеря данных – klesta

ответ

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() второй раз с тем же условием, второй вызов завершается с ошибкой. Что именно я хотел. Спасибо всем за помощь.

+0

Это сработало отлично. О, ты мой герой! Ты сделал свой день, теперь ты счастливый человек. – stej

0

В этом случае лучше реализовать очередь, чтобы действовать как флаг. Вы создадите и отправите сообщение в очередь в качестве запроса на создание своего блога страницы. Таким образом, только одна машина отключит сообщение, а затем вызовет ваш метод создания страницыBlob.

0

Другой подход заключается в том, чтобы пойти с blob leasing. У вас будет блок-блок и пусть все экземпляры попытаются получить аренду на этом блобе. Только один экземпляр сможет добиться успеха. Экземпляр, который преуспеет, вызовет код для создания blob. В зависимости от того, когда в жизненном цикле вашего приложения вы вызываете операцию, вам все равно придется использовать код выше, чтобы, если blob уже существует, вы не воссоздаете его.

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

Могу ли я получить аренду для несуществующего CloudPageBlob? – klesta

+0

Нет. Должен присутствовать blob. Это должен быть другой blob, который вы пытаетесь создать, и может быть очень маленьким блочным блобом. –

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 с их метаданными одновременно и, таким образом, думая, что они оба являются лидерами).

+0

Создание этого блоба как части предопределения не является решением, поскольку в форме объектов событий все данные приложения хранятся в этом блобе. Размер Blob ограничен, поэтому мне нужно создать новое и новое. Во-вторых, «попробуйте сделать создание, ловушку для исключения, если оно уже существует» - это именно то, что я хочу сделать, но я не знаю, как это сделать. Данные переписываются, и исключение не генерируется. Я рассмотрю ссылки, которые вы опубликовали ... – klesta

+0

Если все экземпляры используют одни и те же данные, но только один отвечает за его обновление, приведенный выше шаблон должен быть действительным. То, что меня все еще путает, - это характер данных. Я не могу не думать, что, возможно, в этом сценарии есть еще больше возможностей, которые вы могли бы поделиться, если есть лучшее решение. – BrentDaCodeMonkey

+0

Каждое действие (которое изменяет данные) представляется как событие. Лидер записывает эти события в blob. Каждый экземпляр потребляет это событие и в результате изменяет его локальное состояние. (Event sourcing [ссылка] (http://martinfowler.com/eaaDev/EventSourcing.html)). По своей природе количество этих событий неограничено :), но размер блоба ограничен. Поэтому мне нужно разбить его на несколько блоков. – klesta