什么是处理Azure Cache中悲观并发的最佳方法?

时间:2013-03-06 04:51:13

标签: azure pessimistic-locking

我是azure缓存的新手,面临一个问题。

我将首先简要介绍一下这个场景。我们使用SQL Azure作为我们的应用程序的DB。为了避免延迟问题和限制问题,我们使用Azure缓存(在Web角色上共存缓存)。通过使用Azure缓存,我们只从DB获取数据一次并将其保留在缓存中以供进一步使用。

由于我们使用的是缓存数据,因此无论何时执行任何DML操作,此处的挑战是始终在SQL Azure DB和Azure Cache之间保持同步数据。我们首先更新数据库,如果更新成功,则使缓存数据无效。这种方法适用于正常情况。 但是,对于并发用户工作和执行更新,似乎存在问题。我们在更新Cache中的数据时使用悲观并发模型。在这里,我们使用瞬态重试策略来确保重试尝试(假设为5秒,固定间隔为1秒)。

示例代码如下所示:

Microsoft.Practices.TransientFaultHandling.RetryPolicy cacheRetryPolicy =
    GetAzureCacheRetryPolicy();

cacheRetryPolicy.Retrying += TransientRetryManager.OnRetrying;  
DataCacheLockHandle handle = null;
cacheRetryPolicy.ExecuteAction(() =>
{
    try
    {
        object obj = cache.GetAndLock(key, TimeSpan.FromSeconds(1), out handle);
        cache.PutAndUnlock(key, value, handle, expirationTime.Value, tags);
    }
    catch (DataCacheException ex)
    {
        if (ex.ErrorCode == DataCacheErrorCode.KeyDoesNotExist)
        {
            cache.Put(key, value, expirationTime.Value, tags);
        }
        else
        { 
            //This means wait till the cache is released. 
            //Throwing from here will allow to retry with Transient 
            //handling retry policy.                           
            throw ex; 
        }
    }
}

此处,等待数量(假设为6)超过重试次数(即我们的情况下为5次)。到第6个轮到它时,重试尝试已经结束,因此第6次Wait有最新更新将无法在缓存中更新它。

有一种方法可以解决此问题,方法是在errorcode objectlocked获取锁定缓存密钥时排队所有等待。

有人可以建议处理此案的最佳方法吗?

1 个答案:

答案 0 :(得分:0)

如果我没有错,缓存结果不会在DB中保存最新数据。

--------------------------------------------------------------------------------
This could happen in following Scenario
--------------------------------------------------------------------------------
Time        User 1                              User 2
1           Updates DB data from A to B         Idle
4           Adding data to cache                Updates DB data from B to C
5           Still adding to cache               Adding data to cache
7           Still adding to cache               caching is done
9           Still adding to cache               current data is C
10          caching is done
11          current data is B (but it should be C)
  1. 用户2在用户1
  2. 之后启动更新
  3. 理想情况下,最新数据应为User 2's
  4. 但用户2的缓存代码在用户1的代码之前完成,然后用户1的缓存代码被解雇
  5. 所以最新的结果将是用户1,这是不期望的。
  6. 如果它是一个单实例应用程序,我们可以使用线程锁解决,因为Azure是多实例,并且有更多的点击APP,你可以采取以下方法。

    也许不是最好的,但我们已经解决了这个问题,即我们的应用程序在6台Web服务器上运行,而且我们的用户数超过75,000。

    我们始终在缓存中保留两个数据

    1. 内容需要缓存的内容
    2. 我们的数据库中针对相同内容的LastModified列的值
    3. 在向缓存添加新值之前,我们始终确保缓存中的LastModified数据小于我们在DB中的日期。 由于任何原因,缓存数据超过当前数据库数据,然后以某种方式将最新值推送到缓存,因此我们不会添加回来。

      So what we have done is
      -----------------------------------------------------------------------------------
      Time                User 1                      User 2
      -----------------------------------------------------------------------------------
      1           Updates DB data from A to B         Idle
      4           Adding data to cache                Updates DB data from B to C     
      5           still adding to cache               Adding data to cache
      7           Still adding to cache               caching is done with last modified date
      9           Still adding to cache               current data is C
      10          found that cached date is greater than the current
      11          skips caching