2

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

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

问题:如何修改它以优雅地处理这种情况?我可以更改数据流或为 Mutex 使用每个用户的“云”锁。在不试图约束任何人的想法的情况下,过去我推测有一个基于 SQL 的云锁,但无法真正让它在 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!
    // ...

}
4

1 回答 1

4

您可以通过 blob 租约将互斥锁放入 blob 存储中。如果其他人使用互斥锁,AcquireLease() 将失败,请尝试/捕获整个事情

                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);
                }
于 2013-01-08T20:44:24.180 回答