云互斥:基于云的并发,涉及对共享数据的读/写(SQL数据)

时间:2013-01-08 20:16:49

标签: entity-framework azure concurrency parallel-processing cloud

后台:我们有一个Azure .NET应用程序,我们需要向多个后端提供商注册一个“前端”用户。由于此注册需要更长时间,因此我们将其卸载到辅助角色,并且有多个辅助角色。所有数据都存储在Azure SQL中,我们使用Entity Framework 5.0作为我们的ORM。我们目前的设置方式是,我们读取来自SQL dB =>工人角色代码中的流程=> /更新到SQL dB以标记完成。基本上我需要解决传统的“多线程+共享数据写入”问题,但不是操作系统规模,而是在云规模上。

关注:如果第一个工作人员的时间超过可见性超时,我们就会遇到多个工作人员的竞争状况。例如,假设有两个工作者角色,我在下面标记了两者如何从SQL读取,认为处理仍处于待处理状态,并且两者都将继续。它导致最后一个作者赢得竞争条件,并在外部服务提供商上创建孤立和额外的帐户。

问题:我如何修改它以优雅地处理这种情况?我可以更改数据流或使用每用户“云”锁定Mutex。在没有试图约束任何人的想法的情况下,过去我推测有一个SQL based cloud lock,但实际上并没有让它在EF5.0中运行。在这里,我试图探索任何答案,基于SQL的锁或不。

// Read message off Service Bus Queue
// message invisible for 1 min now, worker must finish in 1 min
BrokeredMessage qMsg = queueClient.Receive();

// Extract UserID Guid from message
Guid userProfileId = DeserializeUserIdFromQMsg(qMsg); 

// READ PROFILE FROM SQL
UserProfile up = (from x in myAppDbContext.UserProfiles select x).SingleOrDefault(p => p.UserProfileId == userProfileId);

if (up != null)
{
    List<Task> allUserRegTasks = new List<Task>();

    string firstName = up.FirstName; // <== WORKER ROLE #2 HERE
    string lastName = up.LastName;
    string emailAddress = up.Email;

    // Step 1: Async register User with provider #1, update db
    if (String.IsNullOrEmpty(up.Svc1CustId)) 
    {
        // <== WORKER ROLE #1 HERE
        Svc1RegHelper svc1RegHelper = new Svc1RegHelper(); 
        Task svc1UserRegTask = svc1RegHelper.GetRegisterTask(userProfileId, firstName, lastName, emailAddress);
        svc1UserRegTask.Start(); // <== SQL WRITE INSIDE THIS (marks "up.Svc1CustId")
        allUserRegTasks.Add(svc1UserRegTask);
    }

    // Step 2: Async register User with provider #2, update db
    if (String.IsNullOrEmpty(up.Svc2CustId))
    {
        Svc2RegHelper svc2RegHelper = new Svc2RegHelper();
        Task svc2UserRegTask = svc2RegHelper.GetRegisterTask(userProfileId, firstName, lastName, emailAddress);
        svc2UserRegTask.Start(); // <== SQL WRITE INSIDE THIS (marks "up.Svc2CustId")
        allUserRegTasks.Add(svc2UserRegTask);
    }

    Task.WaitAll(allUserRegTasks.ToArray());

    // Step 3: Send confirmation email to user we're ready for them!
    // ...

}

1 个答案:

答案 0 :(得分:4)

您可以通过blob租约将mutex放入blob存储中。如果其他人使用互斥锁,则AcquireLease()会失败,因此在整个过程中放置​​一个try / catch

                var lockBlobContainer = cloudClient.GetContainerReference("mutex-container");
                var lockBlob = lockBlobContainer.GetBlobReference("SOME_KNOWN_KEY.lck");
                lockBlob.UploadText(DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)); //creates the mutex file
                var leaseId = lockBlob.AcquireLease();

                try
                {
                    // Do stuff
                }
                finally
                {
                    lockBlob.ReleaseLease(leaseId);
                }