3

我是天蓝色缓存的新手并面临一个问题。

我先简单介绍一下场景。我们正在SQL Azure为我们的应用程序使用数据库。为了避免延迟问题和限制问题,我们使用 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 次等待将无法在缓存中更新它。

有一种方法可以通过排队所有等待来克服这个问题,以防errorcodeobjectlocked获取缓存键上的锁定时。

谁能建议处理这种情况的最佳方法?

4

1 回答 1

0

如果我没记错的话,缓存结果不会在数据库中保存最新数据。

--------------------------------------------------------------------------------
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. 所以理想情况下,最新数据应该是用户 2 的
  3. 但是用户 2 的缓存代码在用户 1 的代码之前完成,然后用户 1 的缓存代码被触发
  4. 因此,最新结果将是用户 1,这不是预期的。

如果它是一个单实例应用程序我们可以使用线程锁来解决,因为 Azure 是多实例并且对 APP 有更多的命中,你可以做下面的方法。

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

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

  1. 需要缓存的内容
  2. 我们数据库中相同内容的 LastModified 列的值

在向缓存添加新值之前,我们始终确保缓存中的 LastModified 数据小于我们在数据库中的日期。出于某种原因,缓存的数据比当前的数据库数据多,然后不知何故,最新的值已经被推送到缓存,所以我们不加回来。

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
于 2013-09-25T10:22:07.753 回答