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

在Azure缓存中处理悲观并发的最佳方法是什么?,azure,pessimistic-locking,Azure,Pessimistic Locking,我是azure缓存新手,面临一个问题 我将首先简要介绍该场景。我们正在使用sqlazure作为应用程序的数据库。为了避免延迟问题和限制问题,我们正在使用Azure缓存(web角色上的同一位置缓存)。通过使用Azure缓存,我们只从数据库中获取一次数据,并将其保存在缓存中以供进一步使用 因为我们使用的是缓存数据,所以这里的挑战是,无论何时执行任何DML操作,都要始终保持SQL Azure DB和Azure缓存之间的数据同步。我们首先更新数据库,如果更新成功,则使缓存数据无效。这种方法适用于正常场景

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

我将首先简要介绍该场景。我们正在使用
sqlazure
作为应用程序的数据库。为了避免延迟问题和限制问题,我们正在使用Azure缓存(web角色上的同一位置缓存)。通过使用Azure缓存,我们只从数据库中获取一次数据,并将其保存在缓存中以供进一步使用

因为我们使用的是缓存数据,所以这里的挑战是,无论何时执行任何DML操作,都要始终保持SQL Azure DB和Azure缓存之间的数据同步。我们首先更新数据库,如果更新成功,则使缓存数据无效。这种方法适用于正常场景。 然而,由于并发用户在工作和执行更新,似乎存在一个问题。我们在更新缓存中的数据时使用悲观并发模型。在这里,我们使用暂时重试策略来确保重试尝试(假设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次等待将无法在缓存中更新它

有一种方法可以克服此问题,即在获取缓存密钥锁定时,在
errorcode
objectlocked
锁定的情况下,将所有等待排队


有谁能提出处理这个案件的最佳方法吗

若我并没有错的话,缓存的结果并没有在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)
  • 用户2在用户1之后启动更新
  • 因此,理想情况下,最新数据应该是用户2的
  • 但是用户2的缓存代码在用户1的代码之前完成,然后触发用户1的缓存代码
  • 因此,最新的结果将是用户1,这是不期望的
  • 若它是一个单实例应用程序,我们可以使用线程锁来解决,因为Azure是多实例的,而且应用程序的点击率更高,那个么您可以采用以下方法

    也许不是最好的,但是我们已经解决了这个问题,我们的应用程序运行在6台web服务器上,我们有超过75k的用户

    我们总是在缓存中保存两个数据

  • 需要缓存哪些内容
  • 相同内容的数据库中LastModified列的值
  • 在向缓存添加新值之前,我们始终确保缓存中的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