3

I am new to azure caching and facing one problem.

I will brief about the scenario first. We are using SQL Azure as DB for our application. To avoid the latency issues and Throttling issues we are using Azure Caching (co-located caching on web role). By using Azure Caching we are fetching data from DB only once and keeping it in cache for further use.

Since we are using Cached data, challenge here is to always keep in sync data between SQL Azure DB and Azure Cache at any point of time whenever there is any DML operation performed. We are doing this by first updating DB and if update successful invalidating cached data. This approach works fine for normal scenario. However, with concurrent users working and performing updates there seems an issue. We are using pessimistic concurrency model while updating data in Cache. Here, we are using transient retry policy to make ensure retry attempts (let's say 5 times with fixed interval of 1 sec).

The sample code looks like this:

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; 
        }
    }
}

Here, in case number of waits (lets say 6) exceed the number retry attempts (i.e. 5 in our case). By the time 6th comes for its turn, retry attempts are already over and hence 6th Wait which has latest update will fail to update it in cache.

There is one way to overcome this problem by queuing all waits in case errorcode is objectlocked while getting the lock on cache key.

Can anyone please suggest best way of handling this case?

joce
  • 9,624
  • 19
  • 56
  • 74

1 Answers1

0

If I am not wrong, cached result is not holding latest data there in 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. User 2 initiates the update after User 1
  2. So Ideally the latest data should be User 2's
  3. But the caching code of User 2 completes before the User 1's code, then the cache code of user 1 is fired
  4. So the Latest result would be User 1, which is not expected.

If its a single instance application we can solve using thread locks, since Azure is multi instance and there are more hits to APP, you could do following approach.

Maybe not the best, but we have solved this issue where our application is running on 6 web servers and we have more than 75k users.

We always keep two data in cache

  1. Content what need to be cached
  2. Value of LastModified column from our DB for the same content

Before adding new value to cache, we always make sure that the LastModified data in cache is less than what date we have in DB. for any reason the cached data is more than the current DB data, then somehow the latest value is already pushed to cache, so we don't add back.

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
CreativeManix
  • 2,162
  • 1
  • 17
  • 29